我的编程空间,编程开发者的网络收藏夹
学习永远不晚

当在文件中将“+”转义为“\u002b”时,从 JSON 解组“time.Time”失败,但在纯字符串中工作:无法将“\\u002b00:00\””解析为“Z07:00”

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

当在文件中将“+”转义为“\u002b”时,从 JSON 解组“time.Time”失败,但在纯字符串中工作:无法将“\\u002b00:00\””解析为“Z07:00”

学习知识要善于思考,思考,再思考!今天编程网小编就给大家带来《当在文件中将“+”转义为“\u002b”时,从 JSON 解组“time.Time”失败,但在纯字符串中工作:无法将“\\u002b00:00\””解析为“Z07:00”》,以下内容主要包含等知识点,如果你正在学习或准备学习Golang,就都不要错过本文啦~让我们一起来看看吧,能帮助到你就更好了!

问题内容

我正在解组到一个具有名为 foo 的 time.time 字段的结构:

type astructwithtime struct {
    foo time.time `json:"foo"`
}

我的期望是,解组后我会得到这样的结果:

var expectedstruct = astructwithtime{
    foo: time.date(2022, 9, 26, 21, 0, 0, 0, time.utc),
}

工作示例 1:将纯 json 对象转换为结构

这在使用纯 json 字符串时效果很好:

func test_unmarshalling_datetime_from_string(t *testing.t) {
    jsonstrings := []string{
        "{\"foo\": \"2022-09-26t21:00:00z\"}",           // trailing z = utc offset
        "{\"foo\": \"2022-09-26t21:00:00+00:00\"}",      // explicit zero offset
        "{\"foo\": \"2022-09-26t21:00:00\u002b00:00\"}", // \u002b is an escaped '+'
    }
    for _, jsonstring := range jsonstrings {
        var deserializedstruct astructwithtime
        err := json.unmarshal([]byte(jsonstring), &deserializedstruct)
        if err != nil {
            t.fatalf("could not unmarshal '%s': %v", jsonstring, err) // doesn't happen
        }
        if deserializedstruct.foo.unix() != expectedstruct.foo.unix() {
            t.fatal("unmarshalling is erroneous") // doesn't happen
        }
        // works; no errors
    }
}

工作示例 2:将 json 数组转换为切片

如果我将 json 数组中的相同对象解组到切片中,它也可以工作:

func test_unmarshalling_datetime_from_array(t *testing.t) {
    // these are just the same objects as above, just all in one array instead of as single objects/dicts
    jsonarraystring := "[{\"foo\": \"2022-09-26t21:00:00z\"},{\"foo\": \"2022-09-26t21:00:00+00:00\"},{\"foo\": \"2022-09-26t21:00:00\u002b00:00\"}]"
    var slice []astructwithtime // and now i need to unmarshal into a slice
    unmarshalerr := json.unmarshal([]byte(jsonarraystring), &slice)
    if unmarshalerr != nil {
        t.fatalf("could not unmarshal array: %v", unmarshalerr)
    }
    for index, instance := range slice {
        if instance.foo.unix() != expectedstruct.foo.unix() {
            t.fatalf("unmarshalling failed for index %v: expected %v but got %v", index, expectedstruct.foo, instance.foo)
        }
    }
    // works; no errors
}

工作示例

现在,我使用从文件“test.json”读取的 json 进行相同的解组。它的内容是上面工作示例中的数组:

[
  {
    "foo": "2022-09-26t21:00:00z"
  },
  {
    "foo": "2022-09-26t21:00:00+00:00"
  },
  {
    "foo": "2022-09-26t21:00:00\u002b00:00"
  }
]

代码是:

func Test_Unmarshalling_DateTime_From_File(t *testing.T) {
    fileName := "test.json"
    fileContent, readErr := os.ReadFile(filepath.FromSlash(fileName))
    if readErr != nil {
        t.Fatalf("Could not read file %s: %v", fileName, readErr)
    }
    if fileContent == nil {
        t.Fatalf("File %s must not be empty", fileName)
    }
    var slice []AStructWithTime
    unmarshalErr := json.Unmarshal(fileContent, &slice)
    if unmarshalErr != nil {
        // ERROR HAPPENS HERE
        // Could not unmarshal file content test.json: parsing time "\"2022-09-26T21:00:00\\u002b00:00\"" as "\"2006-01-02T15:04:05Z07:00\"": cannot parse "\\u002b00:00\"" as "Z07:00"
        t.Fatalf("Could not unmarshal file content %s: %v", fileName, unmarshalErr)
    }
    for index, instance := range slice {
        if instance.Foo.Unix() != expectedStruct.Foo.Unix() {
            t.Fatalf("Unmarshalling failed for index %v in file %s. Expected %v but got %v", index, fileName, expectedStruct.Foo, instance.Foo)
        }
    }
}

由于转义的“+”而失败。

将时间“2022-09-26t21:00:00\u002b00:00”解析为“2006-01-02t15:04:05z07:00”:无法将“\u002b00:00”解析为“z07:00” ”

问题:为什么从文件中读取 time.time 字段时解组会失败,但从相同字符串读取相同 json 时却可以正常解组?


正确答案


我相信这是 encoding/json 中的错误。

https://www.json.org 处的 json 语法和 RFC 8259, Section 7: Strings 处的 ietf json 定义都规定 json 字符串可以包含 unicode 转义序列:

原始帖子中的 json 文档

{
  "foo": "2022-09-26t21:00:00\u002b00:00"
}   

使用 json.parse() 在 node.js 中完美解析和反序列化。

以下是演示该错误的示例:

package main

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

var document []byte = []byte(`
{
  "value": "2022-09-26t21:00:00\u002b00:00"
}
`)

func main() {

    deserializejsonastime()

    deserializejsonasstring()

}

func deserializejsonastime() {
    fmt.println("")
    fmt.println("deserializing json as time.time ...")

    type widget struct {
        value time.time `json: "value"`
    }

    expected := widget{
        value: time.date(2022, 9, 26, 21, 0, 0, 0, time.utc),
    }
    actual := widget{}
    err := json.unmarshal(document, &actual)

    switch {
    case err != nil:
        fmt.println("error deserializing json as time.time")
        fmt.println(err)
    case actual.value != expected.value:
        fmt.printf("unmarshalling failed: expected %v but got %v\n", expected.value, actual.value)
    default:
        fmt.println("sucess")
    }

}

func deserializejsonasstring() {
    fmt.println("")
    fmt.println("deserializing json as string ...")

    type widget struct {
        value string `json: "value"`
    }

    expected := widget{
        value: "2022-09-26t21:00:00+00:00",
    }
    actual := widget{}
    err := json.unmarshal(document, &actual)

    switch {
    case err != nil:
        fmt.println("error deserializing json as string")
        fmt.println(err)
    case actual.value != expected.value:
        fmt.printf("unmarshalling failed: expected %v but got %v\n", expected.value, actual.value)
    default:
        fmt.println("sucess")
    }

}

运行时 - 请参阅 https://goplay.tools/snippet/fHQQVJ8GfPp - 我们得到:

Deserializing JSON as time.Time ...
Error deserializing JSON as time.Time
parsing time "\"2022-09-26T21:00:00\\u002b00:00\"" as "\"2006-01-02T15:04:05Z07:00\"": cannot parse "\\u002b00:00\"" as "Z07:00"

Deserializing JSON as string ...
Sucess

由于将包含 unicode 转义序列的 json 字符串反序列化为 string 会产生正确/预期的结果 - 转义序列被转换为预期的符文/字节序列 - 问题似乎在于处理 time.time 反序列化的代码(它似乎没有反序列化为字符串,然后将字符串值解析为 time.time

今天关于《当在文件中将“+”转义为“\u002b”时,从 JSON 解组“time.Time”失败,但在纯字符串中工作:无法将“\\u002b00:00\””解析为“Z07:00”》的内容介绍就到此结束,如果有什么疑问或者建议,可以在编程网公众号下多多回复交流;文中若有不正之处,也希望回复留言以告知!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

当在文件中将“+”转义为“\u002b”时,从 JSON 解组“time.Time”失败,但在纯字符串中工作:无法将“\\u002b00:00\””解析为“Z07:00”

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

当在文件中将“+”转义为“\u002b”时,从 JSON 解组“time.Time”失败,但在纯字符串中工作:无法将“\\u002b00:00\””解析为“Z07:00”

学习知识要善于思考,思考,再思考!今天编程网小编就给大家带来《当在文件中将“+”转义为“\u002b”时,从 JSON 解组“time.Time”失败,但在纯字符串中工作:无法将“\\u002b00:00\””解析为“Z07:00”》,以下
当在文件中将“+”转义为“\u002b”时,从 JSON 解组“time.Time”失败,但在纯字符串中工作:无法将“\\u002b00:00\””解析为“Z07:00”
2024-04-04

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录