声明json对象的结构

问题描述

我有一个来自这样的API的JSON响应对象:

[
    {
        "peoples": {
            "1": {"name": "Jhon","age": 123},"2": {"name": "Jhon","3": {"name": "Jhon","4": {"name": "Jhon","_object": true,"_timestamp": "2020-08-05T07:05:55.509Z","_writable": false
        }
    }
]

参数peoples_object_timestamp_writable是固定的。动态值是1,2,3,4...n参数。

该结构中peoples的数量可以大于4或可以为1。是否有用于创建Struct对象或json.Unmarshal的优雅解决方案?

解决方法

借用the input example from Sarath Sadasivan Pillai(请参阅comment),here (link to Playground example)是使用map[string]json.RawMessage和自定义解组功能的一种方法:

package main

import (
    "encoding/json"
    "fmt"
    "strconv"
    "time"
)

type Person struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}

type Keywords struct {
    Object    bool      `json:"_object"`
    Timestamp time.Time `json:"_timestamp"`
    Writable  bool      `json:"_writable"`
}

type Decoded struct {
    People map[string]Person // or perhaps just []Person
    Info   Keywords
}

var input []byte = []byte(`{
        "1": {"name": "Jhon","age": 123},"2": {"name": "Jhon","3": {"name": "Jhon","4": {"name": "Jhon","_object": true,"_timestamp": "2020-08-05T07:05:55.509Z","_writable": false
}`)

// Unmarshal json in the input format outlined by
// the example above: a map of numeric strings to Name/Age pair,// plus some keywords.

func (d *Decoded) UnmarshalJSON(data []byte) error {
    if err := json.Unmarshal(data,&d.Info); err != nil {
        return err
    }
    var m map[string]json.RawMessage
    if err := json.Unmarshal(data,&m); err != nil {
        return err
    }
    if d.People == nil {
        d.People = make(map[string]Person)
    }
    for k := range m {
        // This is the hard part: you must choose how
        // to decide whether to decode this as a Person.
        // Here,we use strconv.Atoi() as in the example
        // by Sarath Sadasivan Pillai,but there are as
        // many options as you can think of.
        //
        // For instance,another method would be to try
        // decoding the json.RawMessage as a Person.  It's
        // also not clear whether the numeric values imply
        // some particular ordering,which maps discard.
        // (If these come out in order,that's just luck.)
        if _,err := strconv.Atoi(k); err != nil {
            continue
        }
        var p Person
        if err := json.Unmarshal(m[k],&p); err != nil {
            return err
        }
        d.People[k] = p
    }
    return nil
}

func main() {
    var x Decoded
    err := json.Unmarshal(input,&x)
    if err != nil {
        fmt.Printf("failed: %v\n",err)
    } else {
        fmt.Printf("succeeded:\n%#v\n",x.Info)
        for k := range x.People {
            fmt.Printf("person %q = %#v\n",k,x.People[k])
        }
    }
}

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...