2 回答
TA贡献1785条经验 获得超4个赞
您可以使用该json.RawMessage类型来推迟解组某些 JSON 文本值。如果您使用这种类型,那么 JSON 文本将存储在其中而无需解组(因此您可以稍后根据需要解组此片段)。
因此,在您的情况下,如果您尝试解组成一个这样的切片RawMessage,您可以使用您在问题中链接的技术,即您可以迭代原始值的切片(每个值的 JSON 文本Data),创建一个Datastruct 将您想要的值作为缺失值的默认值,并将切片元素解组到这个准备好的结构中。就这样。
它看起来像这样:
allJson := []json.RawMessage{}
if err := json.Unmarshal(src, &allJson); err != nil {
panic(err)
}
allData := make([]Data, len(allJson))
for i, v := range allJson {
// Here create your Data with default values
allData[i] = Data{Valid: true}
if err := json.Unmarshal(v, &allData[i]); err != nil {
panic(err)
}
}
在Go Playground上试一试。
注释/变体
为了提高效率(为了避免复制结构体),您还allData可以在上面的示例中使成为一个指针切片,如下所示:
allData := make([]*Data, len(allJson))
for i, v := range allJson {
// Here create your Data with default values
allData[i] = &Data{Valid: true}
if err := json.Unmarshal(v, allData[i]); err != nil {
panic(err)
}
}
如果您想继续使用非指针,为了提高效率,您可以在切片元素本身中“准备”您想要的默认值,如下所示:
allData := make([]Data, len(allJson))
for i, v := range allJson {
// Here set your default values in the slice elements
// Only set those which defer from the zero values:
allData[i].Valid = true
if err := json.Unmarshal(v, &allData[i]); err != nil {
panic(err)
}
}
TA贡献1796条经验 获得超10个赞
您可以通过UnmarshalJSON在您的类型上提供一种方法来使其透明并自动工作,即使您的类型在结构或切片中找到,您也可以做一个很好的技巧。
func (d *Data) UnmarshalJSON(j []byte) error {
type _Data Data // Dummy type to avoid infinite recursion in UnmarshalJSON
tmp := _Data{ // Set defaults here
Valid: true,
}
err := json.Unmarshal(j, &tmp)
if err != nil {
return err
}
*d = Data(tmp)
return nil
}
类型的_Data存在只是为了让我们可以调用json.Unmarshal(j, &tmp)并获得原始的未覆盖行为,而不是调用UnmarshalJSON我们已经在中间的方法。我们可以tmp使用您已经链接到的技巧设置默认值。然后在解组完成后,我们可以转换tmp为,Data因为毕竟Data和_Data确实是相同的类型。
鉴于这种方法,您可以简单地
var structs []Data
err := json.Unmarshal(input, &structs)
(或同样使用 a json.Decoder)并让它按照您想要的方式工作。
- 2 回答
- 0 关注
- 333 浏览
添加回答
举报