dqellle310167 2019-04-07 22:26
浏览 51

使用任意键/值对解组JSON以构造

Problem

Found many similar questions (title) but none solved my problem, so here is it.

I have a JSON string that contains some known fields (should always be present) plus any number of unknown/arbitrary fields.

Example

{"known1": "foo", "known2": "bar", "unknown1": "car", "unknown2": 1}

In this example known1 and known2 are known fields. unknown1 and unknown2 are arbitrary/unknown fields.

The unknown fields can have any name (key) and any value. The value type can be either a string, bool, float64 or int.

What I want is to find the simplest and most elegant (idiomatic) way to parse a message like this.

My solution

I've used the following struct:

type Message struct {
    Known1   string `json:"known1"`
    Known2   string `json:"known2"`
    Unknowns []map[string]interface{}
}

Expected result

With this struct and the above sample JSON message I want to achieve a Message like the following (output from fmt.Printf("%+v", msg)):

{Known1:foo Known2:bar Unknowns:[map[unknown1:car] map[unknown2:1]]}

Attempts

1. Simple unmarshal

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

This doesn't work, Unknowns is not filled with the remaining unknown key/value pairs as expected.

2. Double unmarshal

https://play.golang.org/p/Mw6fOYr-Km8

This works but I needed two unmarshals, one to fill the known fields (using an alias type to avoid an infinite loop) and a second one to get all fields as a map[string]interface{} and process the unknowns.

3. Unmarshal and type conversion

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

This works and seems the best option among my solutions.

Any other option?

Option 2 and 3 work but I'm curious if anyone has a simpler/more elegant solution.

  • 写回答

2条回答 默认 最新

  • dongxing2030 2019-04-08 01:33
    关注

    TMTOWTDI, and I think you found a reasonable solution. Another option you could consider -- which I guess is similar to your option 2 -- is to unmarshal it onto a map[string]interface{}.

    Then range over the keys and values and do whatever you need to with the data, running type assertions on the values as necessary. Depending on what you need to do, you may skip the struct entirely, or still populate it.

    package main
    
    import (
        "encoding/json"
        "fmt"
    )
    
    func main() {
        jsonMsg := `{"known1": "foo", "known2": "bar", "unknown1": "car", "unknown2": 1}`
        var msg map[string]interface{}
        fmt.Println(json.Unmarshal([]byte(jsonMsg), &msg))
        fmt.Printf("%+v", msg)
    }
    

    prints

    <nil>
    map[known1:foo known2:bar unknown1:car unknown2:1]
    

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

    评论

报告相同问题?

悬赏问题

  • ¥15 python变量和列表之间的相互影响
  • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值
  • ¥15 我想咨询一下路面纹理三维点云数据处理的一些问题,上传的坐标文件里是怎么对无序点进行编号的,以及xy坐标在处理的时候是进行整体模型分片处理的吗
  • ¥15 CSAPPattacklab
  • ¥15 一直显示正在等待HID—ISP
  • ¥15 Python turtle 画图
  • ¥15 关于大棚监测的pcb板设计
  • ¥15 stm32开发clion时遇到的编译问题
  • ¥15 lna设计 源简并电感型共源放大器
  • ¥15 如何用Labview在myRIO上做LCD显示?(语言-开发语言)