Home > Backend Development > Golang > How to unmarshal json into a struct without mapping all elements while retaining all information

How to unmarshal json into a struct without mapping all elements while retaining all information

王林
Release: 2024-02-05 21:36:04
forward
484 people have browsed it

如何将 json 解组为结构体而不映射所有元素,同时保留所有信息

Question content

I receive a JSON object from a queue. I want to process part of the object and update it before sending to another queue.

If I have an input

{
  "one": "data1",
  "two": "data2",
  "three": "data3",
  ...
}
Copy after login

I want to take one and two and calculate some information before adding a new output and sending a similar message

{
  "one": "data1UPDATED",
  "two": "data2",
  "three": "data3",
  ...
  "extra_info": "extra"
}
Copy after login

To be able to process the data better, I want to unmarshal the JSON into a similar structure

type Message struct {
 One string `json:one`
 Two string `json:two`
}
Copy after login

But don't want to map all the fields because many of them are irrelevant to this application and others may change.

Things I've Tried

I tried mapping all fields to json.RawMessage

type Message struct {
 One string `json:"one"`
 Two string `json:"two"`
 ExtraFields json.RawMessage `json:"-"`
}
Copy after login

However, when marshalling the structure, fields contained in ExtraFields are not included.

{
  "one": "data1",
  "two": "data2"
}
Copy after login

I also tried writing a custom unmarshalling that stores the complete message in a struct, with the useful message in one element and the other information in another field

type TmpMessage struct{
  Msg Message
  Others json.RawMessage
}
Copy after login

But this is getting very confusing and I'm hoping for a cleaner solution.

Is there a way to do this, or is the only option without unmarshalling into a struct and just using the raw map[string] interface{}?


Correct answer


You can write a custom unmarshaler, for example:

https://www.php.cn/link/a73d9b34d6f7c322fa3e34c633b1297d

func (m *Message) UnmarshalJSON(data []byte) error {
  tmp := make(map[string]interface{})
  if err := json.Unmarshal(data, &tmp); err != nil {
    return err
  }
  t := reflect.TypeOf(*m)
  for i := 0; i < t.NumField(); i++ {
    f := t.Field(i)
    if f.Name != "ExtraFields" {
      jsonTag := f.Tag.Get("json")
      // this part should probably by a type switch...
      reflect.ValueOf(m).Elem().Field(i).SetString(tmp[jsonTag].(string))
      delete(tmp, jsonTag)
    }
  }
  var err error
  m.ExtraFields, err = json.Marshal(tmp)
  return err
}
Copy after login

The above is the detailed content of How to unmarshal json into a struct without mapping all elements while retaining all information. For more information, please follow other related articles on the PHP Chinese website!

source:stackoverflow.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template