Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
封送和解封送JSON正文,而不涉及所有字段_Json_Go_Unmarshalling - Fatal编程技术网

封送和解封送JSON正文,而不涉及所有字段

封送和解封送JSON正文,而不涉及所有字段,json,go,unmarshalling,Json,Go,Unmarshalling,我正在寻找一种不必为所有字段指定目标就可以解组JSON主体的方法。然后是一个能够“remarshal”身体的隐式场未被触及 像这样的东西会很好,但不会像预期的那样工作:() 给出输出 {"field1": "value1", "field2": "value2"} {Field1:value1 X:map[]} {"field1":"value1"} 我的预期结果是unmarshalledTransaction包含X字段中的“剩余”字段。当再次编组时,它们将被恢复 可以这样做吗?您需要实现Ma

我正在寻找一种不必为所有字段指定目标就可以解组JSON主体的方法。然后是一个能够“remarshal”身体的隐式场未被触及

像这样的东西会很好,但不会像预期的那样工作:()

给出输出

{"field1": "value1", "field2": "value2"}
{Field1:value1 X:map[]}
{"field1":"value1"}
我的预期结果是
unmarshalledTransaction
包含
X
字段中的“剩余”字段。当再次编组时,它们将被恢复


可以这样做吗?

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

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
}

如果您想要一个通用的解决方案(可以在不事先知道字段的情况下使用任何结构),您可以实现一个函数,将正文解封送到结构中,并返回“剩余”字段

为此,您还需要实现一个函数,该函数将任何给定的结构转换为映射(然后用于以通用方式操作映射,而不是预先已知的结构)

像这样:

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字符串相同的工作示例:


您可以解组到一个
映射[string]接口{}
然后手动映射结构实际具有的任何字段,并在执行时将其删除。这将给您留下一张未映射字段的地图。那有什么用吗?可能。你能提供一个工作示例作为答案吗?也许我应该在我的原始帖子中提到这一点,但在我的实际业务场景中,
field1
属于
time.time
类型,现在在解组时会出现问题。你知道有什么方法可以绕过这个问题吗?把这个标记为已接受,因为它以一种优雅的方式回答了最初的问题。谢谢关于
时间
,我不太乐意再次解析时间。我更希望能够在
json
库中使用隐式解析,例如,不必指定格式字符串。因为我的数据来自多个来源(MySQL和Postgres),在时间字符串上有不同的格式。
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
}