doulu2576
doulu2576
2016-07-24 01:04
浏览 193

在golang中解析JSON的子部分

I have an app that receives messages which are JSON. The JSON has various "sections" (example below). Each section has a name, but the structure beyond that is completely different per section.

What I want to do is go through the sections and for each, Unmarshal into the appropriate object. But strangely I've found this difficult, as it seems you can either Unmarshal the entire JSON into an object, or you can get a generic map[string]interface{}. All the example code I've found gets into type switching and manually assigning variables...I was hoping to do the neato Unmarshal directly into an object.

Is there a way to feed Unmarshal a subset of the JSON? I could slice and dice the byte[] myself but that seems ghastly...surely others have experienced something like this?

Here is what I've played with.

package main

import "encoding/json"

type Book struct {
    Author string
    Title  string
    Price  float64
}

type Movie struct {
    Title  string
    Year   float64
    Stars  float64
    Format string
}

var sections map[string]interface{}

func main() {

    /*
     * "Book" and "Movie" are "sections".
     * There are dozens of possible section types,
     * and which are present is not known ahead of time
     */

    incoming_msg_string := `
{
    "Book" : {
        "Author" : "Jack Kerouac",
        "Title" : "On the Road",
        "Price" : 5.99
    }, 
    "Movie" : {
        "Title" : "Sherlock Holmes vs. the Secret Weapon",
        "Year" : 1940,
        "Stars" : 2.5,
        "Format" : "DVD"
    }
}`

    /*
     * this code gets me a list of sections
     */

    var f interface{}
    err := json.Unmarshal([]byte(incoming_msg_string), &f)
    if err != nil {
        panic(err)
    }

    var list_of_sections []string
    for section_type, _ := range f.(map[string]interface{}) {
        list_of_sections = append(list_of_sections, section_type)
    }

    /*
       * next I would like to take the JSON in the "book" section
       * and unmarshal it into a Book object, then take the JSON
       * in the "movie" section and unmarshal it into a Movie object,
       * etc.
       *
       * https://blog.golang.org/json-and-go has an example on
       * decoding arbitrary data, but there's only one Unmarshaling.
       *
       * json.RawMessage has an example in the docs but it assumes
       * the objects are the same type (I think).  My attempts to use
       * it with a two-field struct (section name, and a raw message)
       * gave runtime errors.  Likewise unmarshaling into a 
       * []json.RawMessage gave "panic: json: cannot unmarshal object into Go value of type []json.RawMessage"
       *
       * What I'm looking for is something like:
       *   json.Unmarshal(some_json["a certain section"],&object)
       *
    */
}

Any breadcrumb trail hints much appreciated.

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

1条回答 默认 最新

  • dotwc62080
    dotwc62080 2016-07-24 02:20
    已采纳

    Do your initial unmarshal to a type Sections map[string]json.RawMessage variable. You will then have the section type and the raw data associated with it. You can either switch on the section type and unmarshal to the specific section struct or unmarshal to a map[string]interface{} and handle them generically. (Whatever works best for your app.)

    点赞 评论

相关推荐