为了账号安全,请及时绑定邮箱和手机立即绑定

Go 中的 JSON 解析 - 技巧

Go 中的 JSON 解析 - 技巧

Go
长风秋雁 2023-05-08 14:56:25
如何使用 Go 解析这个 json? timelinedata := '{   "2016-08-17T00:00:00.000Z": 4,   "2016-11-02T00:00:00.000Z": 1,   "2017-08-30T00:00:00.000Z": 1   } '我希望通过遍历 json 将日期和值放在单独的变量中。目前我正在这样做var timeline map[string]intjson.Unmarshal([]byte(timelinedata),for k, v := range timeline {            new_key := k            new_val := v            println("val--->>", new_key, new_val)        }问题是输出的顺序不正确,就像 json 输入一样。每次我运行循环时,输出顺序都不同。我想按照输入的确切顺序映射 json。我想我没有以正确的方式映射它---
查看完整描述

1 回答

?
饮歌长啸

TA贡献1951条经验 获得超3个赞

你不应该假设 JSON 对象中的键顺序意味着什么:

从RFC 7159 的介绍(强调我的):

对象是零个或多个名称/值对的无序集合,其中名称是字符串,值是字符串、数字、布尔值、空值、对象或数组。

数组是零个或多个值的有序序列

除此之外,您不应该假设 JSON 文档的制作者已经控制了键/值顺序;地图在大多数语言中都是无序的,所以它主要归结为使用的编码库。如果生产者确实关心顺序,他们会使用数组。

也就是说,如果您真的对 JSON 键的顺序感兴趣,则必须使用json.Decoder.Token逐个解码对象:

package main


import (

    "encoding/json"

    "fmt"

    "log"

    "strings"

)


func main() {

    j := `{

        "2016-08-17T00:00:00.000Z": 4,

        "2016-11-02T00:00:00.000Z": 1,

        "2017-08-30T00:00:00.000Z": 1

    }`


    dec := json.NewDecoder(strings.NewReader(j))

    for dec.More() {

        t, err := dec.Token()

        if err != nil {

            log.Fatal(err)

        }


        switch t := t.(type) {

        case json.Delim:

            // no-op

        case string:

            fmt.Printf("%s => ", t)

        case float64:

            fmt.Printf("%.0f\n", t)

        case json.Number:

            fmt.Printf(" %s\n", t)

        default:

            log.Fatalf("Unexpected type: %T", t)

        }

    }

}


查看完整回答
反对 回复 2023-05-08
  • 1 回答
  • 0 关注
  • 92 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信