通过更改JSON属性取消编组

时间:2018-06-24 03:37:19

标签: json go struct

我有一个JSON对象,其详细信息可以包含不同类型的JSON对象,其余JSON保持不变,在这种情况下,我如何在Golang中使用单个结构来处理两种类型的JSON

JSON 1:

{
   "field1":"",
   "field2":"",
   "field3":"",
   "field4":"",
   "field5":"",
   "field6":"",
   "field7":"",
   "details":{
      "detail1":"",
      "detail2":[
         {
            "arr1":"",
            "arr2":{
               "id":"",
               "name":""
            },
            "list":[
               {
                  "id":"",
                  "version":1,
                  "name":""
               }
            ]
         }
      ]
   },
   "user":{
      "id":"",
      "name":""
   }
}

JSON 2:

{
   "field1":"",
   "field2":"",
   "field3":"",
   "field4":"",
   "field5":"",
   "field6":"",
   "field7":"",
   "details":{
      "anotherdetail1":"",
      "anotherdetail2":[
         {
            "arr7":"",
            "arr8":{
               "id":"",
               "name":""
            },
            "arr10":{

            }
         }
      ]
   },
   "user":{
      "id":"",
      "name":""
   }
}

我的目标是对这两个JSON对象使用单个结构。在Java之类的语言中,我将创建一个父类,该类以通用的方式类似于细节,并具有2个子类以类似于变化的细节类型,并且在运行时,我将创建一个子类型的对象并将其分配给Parent。我不确定Go中该如何完成。

2 个答案:

答案 0 :(得分:3)

除非可以使用字符串接口映射,否则我不确定您是否可以使用单个结构,但是可以通过将 details 设置为json.RawMessage类型来防止对其进行解码他构造。然后,您可以通过尝试将未知类型的json数据解码为一种类型来对其进行解码,如果返回错误,则尝试使用下一种类型。

这是一些代码,应该可以使您更好地了解我在说什么。

https://play.golang.org/p/06owmiJXNaO

package main

import (
    "encoding/json"
    "fmt"
)

const json1 = `{"name": "foo", "details":[1, 2, 3]}`
const json2 = `{"name": "foo", "details":{"a": [1, 2, 3]}}`

type data struct {
    Name    string          `json:"name"`
    Details json.RawMessage `json:"details"`
}

type detailsone []int

type detailstwo struct {
    A []int `json:"a"`
}

func main() {
    var d1, d2 data
    json.Unmarshal([]byte(json1), &d1)
    json.Unmarshal([]byte(json2), &d2)

    fmt.Printf("%+v\n", d1)
    fmt.Printf("%+v\n", d2)

    var err error
    var b1 detailsone
    var b2 detailstwo

    // json1
    err = json.Unmarshal([]byte(d1.Details), &b1)
    if err == nil {
        fmt.Printf("d1 is an []int: %+v\n", b1)
    }
    err = json.Unmarshal([]byte(d1.Details), &b2)
    if err == nil {
        fmt.Printf("d1 is an detailstwo struct: %+v\n", b2)
    }

    // json2
    err = json.Unmarshal([]byte(d2.Details), &b1)
    if err == nil {
        fmt.Printf("d2 is an []int: %+v\n", b1)
    }
    err = json.Unmarshal([]byte(d2.Details), &b2)
    if err == nil {
        fmt.Printf("d2 is an detailstwo struct: %+v\n", b2)
    }
}

答案 1 :(得分:0)

type Base struct {
    Data map[string]interface{}

    Details struct {
        *D1
        *D2
    } `json:"details"
}

type D1 struct {
    Detail1 string
    Detail2 string
}

type D2 struct {
    AnotherDetail1 string
    AnotherDetail2 string
}

您可以通过将填充的结构与nil进行比较来找到填充的结构