Marshal和unmarshal JSON主体没有触及所有字段

时间:2017-11-08 20:08:53

标签: json go unmarshalling

我正在寻找一种解组JSON主体的方法,而无需为所有字段指定目标。然后是一个能够重新制造"隐含领域的身体未受影响。

这样的事情会很好,但不会像预期的那样奏效:(https://play.golang.org/p/fnVOKrmiFj

<div id='cssmenu'>
  <ul>
    <li><a href='#'>Home</a>
      <ul>
        <li><a href='#'>Product 1</a></li>
        <li><a href='#'>Product 2</a></li>
        <li><a href='#'>Product 3</a></li>
      </ul>


    </li>
    <li><a class='active' href='#'>Products</a>

    </li>
    <li><a href='#'>About</a>
    </li>
    <li><a href='#'>Contact</a></li>
  </ul>
</div>

提供输出

package main

import (
    "encoding/json"
    "fmt"
)

type Transaction struct {
    Field1  string                  `json:"field1"`
    X       map[string]interface{}  `json:"-"`
}

func main() {
    body := []byte(`{"field1": "value1", "field2": "value2"}`)
    fmt.Printf("%+v\n", string(body))

    var unmarshalledTransaction Transaction
    json.Unmarshal(body, &unmarshalledTransaction)
    fmt.Printf("%+v\n", unmarshalledTransaction)

    remarshalledTransaction, _ := json.Marshal(&unmarshalledTransaction)
    fmt.Printf("%+v\n", string(remarshalledTransaction))    
}

我的预期结果是{"field1": "value1", "field2": "value2"} {Field1:value1 X:map[]} {"field1":"value1"} 包含&#34;剩余的&#34; unmarshalledTransaction字段中的字段。然后在再次编组时恢复它们。

可以这样做吗?

2 个答案:

答案 0 :(得分:1)

您需要实现MarshalJSONUnmarshalJSON接口,并编写自己的逻辑以将字段重新映射到适当的位置:

func (t *Transaction) MarshalJSON() ([]byte, error) {
    data := t.X
    data["field1"] = t.Field1
    return json.Marshal(data)
}

func (t *Transaction) UnmarshalJSON(data []byte) error {
    m := make(map[string]interface{})
    json.Unmarshal(data, &m)
    t.Field1 = m["field1"].(string)
    delete(m, "field1")
    t.X = m
    return nil
}

https://play.golang.org/p/KBGAsXB0xA

答案 1 :(得分:0)

如果你想要一个通用的解决方案(可以在不事先知道字段的情况下使用任何结构),你可以实现一个将主体解组为结构并返回“剩余”字段的函数。 p>

为此,您还需要实现一个将任何给定结构转换为地图的函数(用于以通用方式操作地图而不是预先知道的结构)。

像这样:

func structToMap(object interface{}) (map[string]interface{}, error) {
    tempJson, err := json.Marshal(object)
    if err != nil {
       return nil, err
    }
    var theMap map[string]interface{}
    err = json.Unmarshal(tempJson, &theMap)
    if err != nil {
        return nil, err
    }
    return theMap, nil
}

然后:

func unmarshalWithLeftovers(jsonBody []byte, target interface{}) (map[string]interface{}, error) {
    err := json.Unmarshal(jsonBody, target)
    if err != nil {
        return nil, err
    }
    structMap, err := structToMap(target)
    if err != nil {
        return nil, err
    }
    var leftOvers map[string]interface{}
    err = json.Unmarshal(jsonBody, &leftOvers)
    if err != nil {
        return nil, err
    }
    for k, _ := range structMap {
        delete(leftOvers, k)
    }
    return leftOvers, nil
}

然后,您可以以类似的方式组合结构和剩余地图,以重新编组所有内容。

请在此处查看您在问题中使用的具有相同类型和json字符串的工作示例:

https://play.golang.org/p/Fot6YVurHH