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