Unmarshal nested JSON into flat struct in Go [duplicate]












-1
















This question already has an answer here:




  • Unmarshaling nested JSON objects in Golang

    8 answers




Suppose I define a struct as following:



type User struct {
ID string
Name string
Age uint
City string `json:"address.city"`
Province string `json:"address.province"`
}


I am able to take a User struct, and expand out the flattened fiends into a nested JSON structure, with an address object. I'm struggling however to go in the other direction.



How would I take the following JSON:



{
"ID": "1",
"Name": "Keith Baldwin",
"Age": 30,
"address": {
"city": "Saskatoon",
"province": "Saskatchewan"
}
}


And unmarshal it into the given struct?



Is there something I'm missing, or will I just have to write it from scratch, probably using reflection?



Thanks










share|improve this question













marked as duplicate by Volker go
Users with the  go badge can single-handedly close go questions as duplicates and reopen them as needed.

StackExchange.ready(function() {
if (StackExchange.options.isMobile) return;

$('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');

$hover.hover(
function() {
$hover.showInfoMessage('', {
messageElement: $msg.clone().show(),
transient: false,
position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
dismissable: false,
relativeToBody: true
});
},
function() {
StackExchange.helpers.removeMessages();
}
);
});
});
Nov 20 '18 at 5:55


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.




















    -1
















    This question already has an answer here:




    • Unmarshaling nested JSON objects in Golang

      8 answers




    Suppose I define a struct as following:



    type User struct {
    ID string
    Name string
    Age uint
    City string `json:"address.city"`
    Province string `json:"address.province"`
    }


    I am able to take a User struct, and expand out the flattened fiends into a nested JSON structure, with an address object. I'm struggling however to go in the other direction.



    How would I take the following JSON:



    {
    "ID": "1",
    "Name": "Keith Baldwin",
    "Age": 30,
    "address": {
    "city": "Saskatoon",
    "province": "Saskatchewan"
    }
    }


    And unmarshal it into the given struct?



    Is there something I'm missing, or will I just have to write it from scratch, probably using reflection?



    Thanks










    share|improve this question













    marked as duplicate by Volker go
    Users with the  go badge can single-handedly close go questions as duplicates and reopen them as needed.

    StackExchange.ready(function() {
    if (StackExchange.options.isMobile) return;

    $('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
    var $hover = $(this).addClass('hover-bound'),
    $msg = $hover.siblings('.dupe-hammer-message');

    $hover.hover(
    function() {
    $hover.showInfoMessage('', {
    messageElement: $msg.clone().show(),
    transient: false,
    position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
    dismissable: false,
    relativeToBody: true
    });
    },
    function() {
    StackExchange.helpers.removeMessages();
    }
    );
    });
    });
    Nov 20 '18 at 5:55


    This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.


















      -1












      -1








      -1









      This question already has an answer here:




      • Unmarshaling nested JSON objects in Golang

        8 answers




      Suppose I define a struct as following:



      type User struct {
      ID string
      Name string
      Age uint
      City string `json:"address.city"`
      Province string `json:"address.province"`
      }


      I am able to take a User struct, and expand out the flattened fiends into a nested JSON structure, with an address object. I'm struggling however to go in the other direction.



      How would I take the following JSON:



      {
      "ID": "1",
      "Name": "Keith Baldwin",
      "Age": 30,
      "address": {
      "city": "Saskatoon",
      "province": "Saskatchewan"
      }
      }


      And unmarshal it into the given struct?



      Is there something I'm missing, or will I just have to write it from scratch, probably using reflection?



      Thanks










      share|improve this question















      This question already has an answer here:




      • Unmarshaling nested JSON objects in Golang

        8 answers




      Suppose I define a struct as following:



      type User struct {
      ID string
      Name string
      Age uint
      City string `json:"address.city"`
      Province string `json:"address.province"`
      }


      I am able to take a User struct, and expand out the flattened fiends into a nested JSON structure, with an address object. I'm struggling however to go in the other direction.



      How would I take the following JSON:



      {
      "ID": "1",
      "Name": "Keith Baldwin",
      "Age": 30,
      "address": {
      "city": "Saskatoon",
      "province": "Saskatchewan"
      }
      }


      And unmarshal it into the given struct?



      Is there something I'm missing, or will I just have to write it from scratch, probably using reflection?



      Thanks





      This question already has an answer here:




      • Unmarshaling nested JSON objects in Golang

        8 answers








      json go marshalling unmarshalling






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 20 '18 at 1:10









      robbieperry22robbieperry22

      777




      777




      marked as duplicate by Volker go
      Users with the  go badge can single-handedly close go questions as duplicates and reopen them as needed.

      StackExchange.ready(function() {
      if (StackExchange.options.isMobile) return;

      $('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
      var $hover = $(this).addClass('hover-bound'),
      $msg = $hover.siblings('.dupe-hammer-message');

      $hover.hover(
      function() {
      $hover.showInfoMessage('', {
      messageElement: $msg.clone().show(),
      transient: false,
      position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
      dismissable: false,
      relativeToBody: true
      });
      },
      function() {
      StackExchange.helpers.removeMessages();
      }
      );
      });
      });
      Nov 20 '18 at 5:55


      This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.






      marked as duplicate by Volker go
      Users with the  go badge can single-handedly close go questions as duplicates and reopen them as needed.

      StackExchange.ready(function() {
      if (StackExchange.options.isMobile) return;

      $('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
      var $hover = $(this).addClass('hover-bound'),
      $msg = $hover.siblings('.dupe-hammer-message');

      $hover.hover(
      function() {
      $hover.showInfoMessage('', {
      messageElement: $msg.clone().show(),
      transient: false,
      position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
      dismissable: false,
      relativeToBody: true
      });
      },
      function() {
      StackExchange.helpers.removeMessages();
      }
      );
      });
      });
      Nov 20 '18 at 5:55


      This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.


























          3 Answers
          3






          active

          oldest

          votes


















          1














          Create userInfo class



          type UserInfo struct {
          ID string `json:"ID"`
          Name string `json:"Name"`
          Age int `json:"Age"`
          Address struct {
          City string `json:"city"`
          Province string `json:"province"`
          } `json:"address"`
          }


          Then unmarshal your json data into a userinfo object



          var userInfo UserInfo
          jsonStr := `{
          "ID": "1",
          "Name": "Keith Baldwin",
          "Age": 30,
          "address": {
          "city": "Saskatoon",
          "province": "Saskatchewan"
          }
          }`
          json.Unmarshal(byte(jsonStr), &userInfo)





          share|improve this answer
























          • Here is the Go-playground example what @Ehsan.Saradar explained: play.golang.org/p/Bn_zAsF75JV

            – Abhay Kumar
            Nov 20 '18 at 5:28













          • Thanks for the note. Unfortunately this won't work for me, as I need to be able to do it for any arbitrary data structure, and only flatten fields defined in the struct as json:"something.something".

            – robbieperry22
            Nov 20 '18 at 17:34



















          0














          I think you need create an other Address struct.



          type Address struct {
          City string `json:"city"`
          Province string `json:"province"`
          }

          type User struct {
          ID string `json:"id"`
          Name string `json:"name"`
          Age uint `json:"age"`
          Address Address `json:"address"`
          }





          share|improve this answer































            0














            You could make a temporary struct type to dump that data into that matches the format you expect. e.g.



            type userData struct {
            ID string
            Name string
            Age uint
            address map[string]string
            }


            Although my favorite thing to do is to just dump all of the json into a map with string keys and json.RawMessage as values. This will allow you to unmarshal all of the json into this map, and then unmarshal each individual field however you would want.



            var allData map[string]json.RawMessage
            var user User{}
            //Assuming we first get our json from a request, otherwise use json.Unmarshal(jsonData, &allData)
            err := json.NewDecoder(r.Body).Decode(&allData)
            if err != nil {
            //handle
            }
            err = json.Unmarshal(allData["ID"], &c.ID)
            if err != nil {
            //handle
            }
            var addressMap map[string]string
            err = json.Unmarshal(allData["address"], addressMap)
            if err != nil {
            //handle
            }
            c.City = addressMap["city"]
            c.Province = addressMap["province"]


            I haven't tested any of that code, so it may be error ridden, but it's just meant to convey the idea of converting all of the data into a map of json.RawMessage values and then unmarshalling each property. Normally you'd have a lot more error checking to see if values exist, etc. It's more work, for sure, but it's incredibly flexible and gives you a lot of visibility and power into how the data is handled as opposed to just unmarshalling into a struct and hoping the magic works.






            share|improve this answer






























              3 Answers
              3






              active

              oldest

              votes








              3 Answers
              3






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes









              1














              Create userInfo class



              type UserInfo struct {
              ID string `json:"ID"`
              Name string `json:"Name"`
              Age int `json:"Age"`
              Address struct {
              City string `json:"city"`
              Province string `json:"province"`
              } `json:"address"`
              }


              Then unmarshal your json data into a userinfo object



              var userInfo UserInfo
              jsonStr := `{
              "ID": "1",
              "Name": "Keith Baldwin",
              "Age": 30,
              "address": {
              "city": "Saskatoon",
              "province": "Saskatchewan"
              }
              }`
              json.Unmarshal(byte(jsonStr), &userInfo)





              share|improve this answer
























              • Here is the Go-playground example what @Ehsan.Saradar explained: play.golang.org/p/Bn_zAsF75JV

                – Abhay Kumar
                Nov 20 '18 at 5:28













              • Thanks for the note. Unfortunately this won't work for me, as I need to be able to do it for any arbitrary data structure, and only flatten fields defined in the struct as json:"something.something".

                – robbieperry22
                Nov 20 '18 at 17:34
















              1














              Create userInfo class



              type UserInfo struct {
              ID string `json:"ID"`
              Name string `json:"Name"`
              Age int `json:"Age"`
              Address struct {
              City string `json:"city"`
              Province string `json:"province"`
              } `json:"address"`
              }


              Then unmarshal your json data into a userinfo object



              var userInfo UserInfo
              jsonStr := `{
              "ID": "1",
              "Name": "Keith Baldwin",
              "Age": 30,
              "address": {
              "city": "Saskatoon",
              "province": "Saskatchewan"
              }
              }`
              json.Unmarshal(byte(jsonStr), &userInfo)





              share|improve this answer
























              • Here is the Go-playground example what @Ehsan.Saradar explained: play.golang.org/p/Bn_zAsF75JV

                – Abhay Kumar
                Nov 20 '18 at 5:28













              • Thanks for the note. Unfortunately this won't work for me, as I need to be able to do it for any arbitrary data structure, and only flatten fields defined in the struct as json:"something.something".

                – robbieperry22
                Nov 20 '18 at 17:34














              1












              1








              1







              Create userInfo class



              type UserInfo struct {
              ID string `json:"ID"`
              Name string `json:"Name"`
              Age int `json:"Age"`
              Address struct {
              City string `json:"city"`
              Province string `json:"province"`
              } `json:"address"`
              }


              Then unmarshal your json data into a userinfo object



              var userInfo UserInfo
              jsonStr := `{
              "ID": "1",
              "Name": "Keith Baldwin",
              "Age": 30,
              "address": {
              "city": "Saskatoon",
              "province": "Saskatchewan"
              }
              }`
              json.Unmarshal(byte(jsonStr), &userInfo)





              share|improve this answer













              Create userInfo class



              type UserInfo struct {
              ID string `json:"ID"`
              Name string `json:"Name"`
              Age int `json:"Age"`
              Address struct {
              City string `json:"city"`
              Province string `json:"province"`
              } `json:"address"`
              }


              Then unmarshal your json data into a userinfo object



              var userInfo UserInfo
              jsonStr := `{
              "ID": "1",
              "Name": "Keith Baldwin",
              "Age": 30,
              "address": {
              "city": "Saskatoon",
              "province": "Saskatchewan"
              }
              }`
              json.Unmarshal(byte(jsonStr), &userInfo)






              share|improve this answer












              share|improve this answer



              share|improve this answer










              answered Nov 20 '18 at 3:36









              Ehsan.SaradarEhsan.Saradar

              45337




              45337













              • Here is the Go-playground example what @Ehsan.Saradar explained: play.golang.org/p/Bn_zAsF75JV

                – Abhay Kumar
                Nov 20 '18 at 5:28













              • Thanks for the note. Unfortunately this won't work for me, as I need to be able to do it for any arbitrary data structure, and only flatten fields defined in the struct as json:"something.something".

                – robbieperry22
                Nov 20 '18 at 17:34



















              • Here is the Go-playground example what @Ehsan.Saradar explained: play.golang.org/p/Bn_zAsF75JV

                – Abhay Kumar
                Nov 20 '18 at 5:28













              • Thanks for the note. Unfortunately this won't work for me, as I need to be able to do it for any arbitrary data structure, and only flatten fields defined in the struct as json:"something.something".

                – robbieperry22
                Nov 20 '18 at 17:34

















              Here is the Go-playground example what @Ehsan.Saradar explained: play.golang.org/p/Bn_zAsF75JV

              – Abhay Kumar
              Nov 20 '18 at 5:28







              Here is the Go-playground example what @Ehsan.Saradar explained: play.golang.org/p/Bn_zAsF75JV

              – Abhay Kumar
              Nov 20 '18 at 5:28















              Thanks for the note. Unfortunately this won't work for me, as I need to be able to do it for any arbitrary data structure, and only flatten fields defined in the struct as json:"something.something".

              – robbieperry22
              Nov 20 '18 at 17:34





              Thanks for the note. Unfortunately this won't work for me, as I need to be able to do it for any arbitrary data structure, and only flatten fields defined in the struct as json:"something.something".

              – robbieperry22
              Nov 20 '18 at 17:34













              0














              I think you need create an other Address struct.



              type Address struct {
              City string `json:"city"`
              Province string `json:"province"`
              }

              type User struct {
              ID string `json:"id"`
              Name string `json:"name"`
              Age uint `json:"age"`
              Address Address `json:"address"`
              }





              share|improve this answer




























                0














                I think you need create an other Address struct.



                type Address struct {
                City string `json:"city"`
                Province string `json:"province"`
                }

                type User struct {
                ID string `json:"id"`
                Name string `json:"name"`
                Age uint `json:"age"`
                Address Address `json:"address"`
                }





                share|improve this answer


























                  0












                  0








                  0







                  I think you need create an other Address struct.



                  type Address struct {
                  City string `json:"city"`
                  Province string `json:"province"`
                  }

                  type User struct {
                  ID string `json:"id"`
                  Name string `json:"name"`
                  Age uint `json:"age"`
                  Address Address `json:"address"`
                  }





                  share|improve this answer













                  I think you need create an other Address struct.



                  type Address struct {
                  City string `json:"city"`
                  Province string `json:"province"`
                  }

                  type User struct {
                  ID string `json:"id"`
                  Name string `json:"name"`
                  Age uint `json:"age"`
                  Address Address `json:"address"`
                  }






                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Nov 20 '18 at 1:38









                  KibGzrKibGzr

                  1,466610




                  1,466610























                      0














                      You could make a temporary struct type to dump that data into that matches the format you expect. e.g.



                      type userData struct {
                      ID string
                      Name string
                      Age uint
                      address map[string]string
                      }


                      Although my favorite thing to do is to just dump all of the json into a map with string keys and json.RawMessage as values. This will allow you to unmarshal all of the json into this map, and then unmarshal each individual field however you would want.



                      var allData map[string]json.RawMessage
                      var user User{}
                      //Assuming we first get our json from a request, otherwise use json.Unmarshal(jsonData, &allData)
                      err := json.NewDecoder(r.Body).Decode(&allData)
                      if err != nil {
                      //handle
                      }
                      err = json.Unmarshal(allData["ID"], &c.ID)
                      if err != nil {
                      //handle
                      }
                      var addressMap map[string]string
                      err = json.Unmarshal(allData["address"], addressMap)
                      if err != nil {
                      //handle
                      }
                      c.City = addressMap["city"]
                      c.Province = addressMap["province"]


                      I haven't tested any of that code, so it may be error ridden, but it's just meant to convey the idea of converting all of the data into a map of json.RawMessage values and then unmarshalling each property. Normally you'd have a lot more error checking to see if values exist, etc. It's more work, for sure, but it's incredibly flexible and gives you a lot of visibility and power into how the data is handled as opposed to just unmarshalling into a struct and hoping the magic works.






                      share|improve this answer




























                        0














                        You could make a temporary struct type to dump that data into that matches the format you expect. e.g.



                        type userData struct {
                        ID string
                        Name string
                        Age uint
                        address map[string]string
                        }


                        Although my favorite thing to do is to just dump all of the json into a map with string keys and json.RawMessage as values. This will allow you to unmarshal all of the json into this map, and then unmarshal each individual field however you would want.



                        var allData map[string]json.RawMessage
                        var user User{}
                        //Assuming we first get our json from a request, otherwise use json.Unmarshal(jsonData, &allData)
                        err := json.NewDecoder(r.Body).Decode(&allData)
                        if err != nil {
                        //handle
                        }
                        err = json.Unmarshal(allData["ID"], &c.ID)
                        if err != nil {
                        //handle
                        }
                        var addressMap map[string]string
                        err = json.Unmarshal(allData["address"], addressMap)
                        if err != nil {
                        //handle
                        }
                        c.City = addressMap["city"]
                        c.Province = addressMap["province"]


                        I haven't tested any of that code, so it may be error ridden, but it's just meant to convey the idea of converting all of the data into a map of json.RawMessage values and then unmarshalling each property. Normally you'd have a lot more error checking to see if values exist, etc. It's more work, for sure, but it's incredibly flexible and gives you a lot of visibility and power into how the data is handled as opposed to just unmarshalling into a struct and hoping the magic works.






                        share|improve this answer


























                          0












                          0








                          0







                          You could make a temporary struct type to dump that data into that matches the format you expect. e.g.



                          type userData struct {
                          ID string
                          Name string
                          Age uint
                          address map[string]string
                          }


                          Although my favorite thing to do is to just dump all of the json into a map with string keys and json.RawMessage as values. This will allow you to unmarshal all of the json into this map, and then unmarshal each individual field however you would want.



                          var allData map[string]json.RawMessage
                          var user User{}
                          //Assuming we first get our json from a request, otherwise use json.Unmarshal(jsonData, &allData)
                          err := json.NewDecoder(r.Body).Decode(&allData)
                          if err != nil {
                          //handle
                          }
                          err = json.Unmarshal(allData["ID"], &c.ID)
                          if err != nil {
                          //handle
                          }
                          var addressMap map[string]string
                          err = json.Unmarshal(allData["address"], addressMap)
                          if err != nil {
                          //handle
                          }
                          c.City = addressMap["city"]
                          c.Province = addressMap["province"]


                          I haven't tested any of that code, so it may be error ridden, but it's just meant to convey the idea of converting all of the data into a map of json.RawMessage values and then unmarshalling each property. Normally you'd have a lot more error checking to see if values exist, etc. It's more work, for sure, but it's incredibly flexible and gives you a lot of visibility and power into how the data is handled as opposed to just unmarshalling into a struct and hoping the magic works.






                          share|improve this answer













                          You could make a temporary struct type to dump that data into that matches the format you expect. e.g.



                          type userData struct {
                          ID string
                          Name string
                          Age uint
                          address map[string]string
                          }


                          Although my favorite thing to do is to just dump all of the json into a map with string keys and json.RawMessage as values. This will allow you to unmarshal all of the json into this map, and then unmarshal each individual field however you would want.



                          var allData map[string]json.RawMessage
                          var user User{}
                          //Assuming we first get our json from a request, otherwise use json.Unmarshal(jsonData, &allData)
                          err := json.NewDecoder(r.Body).Decode(&allData)
                          if err != nil {
                          //handle
                          }
                          err = json.Unmarshal(allData["ID"], &c.ID)
                          if err != nil {
                          //handle
                          }
                          var addressMap map[string]string
                          err = json.Unmarshal(allData["address"], addressMap)
                          if err != nil {
                          //handle
                          }
                          c.City = addressMap["city"]
                          c.Province = addressMap["province"]


                          I haven't tested any of that code, so it may be error ridden, but it's just meant to convey the idea of converting all of the data into a map of json.RawMessage values and then unmarshalling each property. Normally you'd have a lot more error checking to see if values exist, etc. It's more work, for sure, but it's incredibly flexible and gives you a lot of visibility and power into how the data is handled as opposed to just unmarshalling into a struct and hoping the magic works.







                          share|improve this answer












                          share|improve this answer



                          share|improve this answer










                          answered Nov 20 '18 at 1:53









                          SlotherooSlotheroo

                          34018




                          34018















                              Popular posts from this blog

                              Can a sorcerer learn a 5th-level spell early by creating spell slots using the Font of Magic feature?

                              Does disintegrating a polymorphed enemy still kill it after the 2018 errata?

                              A Topological Invariant for $pi_3(U(n))$