GVKun编程网logo

json.Unmarshal将嵌套的对象编入字符串或[] byte(嵌套的json怎么取值)

16

以上就是给各位分享json.Unmarshal将嵌套的对象编入字符串或[]byte,其中也会对嵌套的json怎么取值进行解释,同时本文还将给你拓展Azure数据流:从JSON字符串中解析嵌套的对象列表

以上就是给各位分享json.Unmarshal将嵌套的对象编入字符串或[] byte,其中也会对嵌套的json怎么取值进行解释,同时本文还将给你拓展Azure 数据流:从 JSON 字符串中解析嵌套的对象列表 将对象数组解析为字符串数组分解字符串数组解析 JSON 字符串收集解析的对象重新加入原始数据结果、Go json Marshal & UnMarshal 的一点小 trick、Go json 自定义 Unmarshal 避免判断 nil、go json 解析 Marshal 和 Unmarshal等相关知识,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!

本文目录一览:

json.Unmarshal将嵌套的对象编入字符串或[] byte(嵌套的json怎么取值)

json.Unmarshal将嵌套的对象编入字符串或[] byte(嵌套的json怎么取值)

我正在尝试解组一些json,以便嵌套的对象不会被解析,而只是被视为a string[]byte

所以我想得到以下内容:

{    "id"  : 15,    "foo" : { "foo": 123, "bar": "baz" }}

解组为:

type Bar struct {    Id  int64  `json:"id"`    Foo []byte `json:"foo"`}

我收到以下错误:

json: cannot unmarshal object into Go value of type []uint8

游乐场演示

答案1

小编典典

我认为您正在寻找的是包中的RawMessage类型encoding/json

该文档指出:

输入RawMessage [] byte

RawMessage是原始编码的JSON对象。它实现了Marshaler和Unmarshaler,可用于延迟JSON解码或预计算JSON编码。

这是使用RawMessage的工作示例:

package mainimport (    "encoding/json"    "fmt")var jsonStr = []byte(`{    "id"  : 15,    "foo" : { "foo": 123, "bar": "baz" }}`)type Bar struct {    Id  int64           `json:"id"`    Foo json.RawMessage `json:"foo"`}func main() {    var bar Bar    err := json.Unmarshal(jsonStr, &bar)    if err != nil {        panic(err)    }    fmt.Printf("%+v\n", bar)}

输出:

{Id:15 Foo:[123 32 34 102 111 111 34 58 32 49 50 51 44 32 34 98 97 114 34 58
32 34 98 97 122 34 32 125]}

操场

Azure 数据流:从 JSON 字符串中解析嵌套的对象列表 将对象数组解析为字符串数组分解字符串数组解析 JSON 字符串收集解析的对象重新加入原始数据结果

Azure 数据流:从 JSON 字符串中解析嵌套的对象列表 将对象数组解析为字符串数组分解字符串数组解析 JSON 字符串收集解析的对象重新加入原始数据结果

如何解决Azure 数据流:从 JSON 字符串中解析嵌套的对象列表 将对象数组解析为字符串数组分解字符串数组解析 JSON 字符串收集解析的对象重新加入原始数据结果?

我需要从 Azure 数据流中的字符串解析 JSON 数据。到目前为止,我能够使用数据流的“解析”功能解析我的所有数据。但是现在我面临着一个对象列表,我不知道如何解析那个“复杂数组”的值。

我的数据是这样的:
有一些元数据字段(此处为 null)和 Base64 编码的 Body 字段。每个 JSON 文档都在一个单独的 JSON 文件中。

示例数据:

{
    "Metadata": null,"Body": "eyJpZCI6ICIxIiwgImNvdW50IjogMTIsICJwcm9qZWN0cyI6IFt7Imd1aWQiOiaimTIzMTItMTI0MzE0LTEyNDEtMTIzNCIsICJzdGF0dXMiOiAic3RvcHBlZCJ9LHsiZ3VpZCI6ICJjc2lzdi1uZDkyM24tMTM0MS0yMzQxIiwgInN0YXR1cyI6ICJydW5uaW5nIn1dfQ"
}

为了澄清起见,编码的示例数据如下所示:

{
    "Metadata": null,"Body": "{"id": "1","count": 12,"projects": [{"guid": "12312-124314-1241-1234","status": "stopped"},{"guid": "csisv-nd923n-1341-2341","status": "running"}]}"
}

我的目标是拥有一个包含 Body 数据的镶木地板文件。 所以应该有三列:id、count、projects。项目应包含复杂对象的列表。

最终的结果应该是这样的:

Goal


这是结果,当我加载一个 JSON 文件时,其中 Body 数据未编码,而是包含对象列表的纯 JSON。请注意,这对于原始问题是不可行的,其中 JSON 数据是 Base64 编码的。

当我将示例数据加载到数据流中时,投影看起来像这样(如预期):

projection

首先,我需要解码 Base64 Body 然后我可以解析 JSON 字符串:

data flow

解码体在这里完成:

Decode Body

基本解析在这里完成:

enter image description here

如何解析“项目”字段?鉴于数组字段列表中的每个对象都具有相同的架构。

我已经尝试将字段“projects”解析为字符串,并添加另一个解析步骤将此字符串解析为“文档数组”,但结果只是空值..

parse projects string

result of parse projects

解决方法

最终的数据流如下所示:
FinalDataFlow

解析必须分成几个部分。

  • 首先需要将数组解析为字符串数组
  • 必须分解字符串数组
  • 现在,可以解析每个数组条目
  • 可以回收分解后的数组以获得我想要的结构
  • 最后,分解和重新收集的数据可以重新连接到原始数据

将对象数组解析为字符串数组

记住:我要解析的数据是这样的:

{
    "metadata": null,"Body": "{"id": "1","count": 12,"projects": [{"guid": "12312-124314-1241-1234","status": "stopped"},{"guid": "csisv-nd923n-1341-2341","status": "running"}]}"
}

所以首先我需要解析“Body”列,即 BodyDecoded,因为我首先必须从 Base64 解码。对象数组必须被解析为字符串数组。 因此,解析步骤的“输出列类型”如下所示:

(id as string,count as integer,projects as string[])

值写在 BodyContent 列中。为了使接下来的步骤更容易,首先将层次结构扁平化。可以为此使用列模式,但我会在这里明确地这样做:
FlattenHierachy

此外,项目列现在更名为 projectsStringArray

分解字符串数组

现在可以使用“展平”步骤分解 projectsStringArrayExplodeStringArray

id也取到这里,以便以后能够回忆起数组。

结果如下:
DataAfterExplodeStringArray

解析 JSON 字符串

现在每个字符串都可以像往常一样通过“解析”步骤进行解析

(guid as string,status as string)

收集解析的对象

可以使用“collect”函数再次将解析的对象聚合到列表中。 CollectArray

重新加入原始数据

要获得所需的结构,必须将收集的列连接到原始数据。 id 列可用于将数据连接回来。
Join

结果

最终选择后,结构看起来像所需的:
Finally

备注: 感谢来自 Microsoft 的 Erik 的帮助!我太专注于只使用解析步骤来解决它,我没有考虑其他方法来解决这个问题..

Go json Marshal & UnMarshal 的一点小 trick

Go json Marshal & UnMarshal 的一点小 trick

在编写 Web Service 等涉及数据序列化和反序列化的场景,对于 JSON 类型的数据,在 Go 中我们经常会使用到 encoding/json Package。最近微有所感,小水一篇

omitempty

JSON 数据的 UnMarshal 我们经常会配合 Struct Tags 使用,让 Struct 的 Filed 与 JSON 数据的指定 property 绑定。

如果要序列化为 Go Struct 的 JSON 数据对应的 Fields 相关的 JSON properties 是缺失的,我们经常会用 omitempty 标记 Go Fields,序列化时,JSON 数据中缺少的属性将会被设置为 Go 中对应的 zero-value,比如:

package main

import (
    "encoding/json"
    "fmt"
)

type Person struct {
    Name string `json:"name"`
    Age  string `json:"age,omitempty"`
    Weak bool   `json:"weak,omitempty"`
}

func main() {
    jsonData := `{"name":"ShanSan"}`
    req := Person{}
    _ = json.Unmarshal([]byte(jsonData), &req)
    fmt.Printf("%+v", req)
    fmt.Println(req.Age)
}
// output
// {Name:ShanSan Age: Weak:false}
//

Go Playground Link

但上面的例子对于一些场景的处理可能会有问题。看下下面这个例子:

package main

import (
    "encoding/json"
    "fmt"
)

type Person struct {
    Name string `json:"name"`
    Age  string `json:"age,omitempty"`
    Weak bool   `json:"weak,omitempty"`
}

func main() {
    jsonData := `{"name":"ShanSan", "age": ""}`
    req := Person{}
    _ = json.Unmarshal([]byte(jsonData), &req)
    fmt.Printf("%+v", req)
    fmt.Println(req.Age)
}
// output
// {Name:ShanSan Age: Weak:false}
//

可以看到 age 为 "" 时,和缺省时的结果是一样的。很显然,上面的写法,缺省的字段和空字段是没有被区分开的。对于一些数据的 Update 操作,比如我们只想 Update Name 字段,对应的 JSON 数据为 {"name":"ShanSan"},执行上述的反序列化动作,Age 字段会被设置为 empty string,Waek 也被设置为了 false,这显然不是我们想看到的。

nil 一下

我们可以指针类型(pointer type)对上面的情况区分一下:

package main

import (
    "encoding/json"
    "fmt"
)

type Person struct {
    Name *string `json:"name"`
    Age  *string `json:"age,omitempty"`
    Weak *bool   `json:"weak,omitempty"`
}

func main() {
    jsonData := `{"name":"ShanSan"}`
    jsonDataEmptyAge := `{"name":"ShanSan", "age": ""}`
    req := Person{}
    reqEmptyAge := Person{}
    _ = json.Unmarshal([]byte(jsonData), &req)
    _ = json.Unmarshal([]byte(jsonDataEmptyAge), &reqEmptyAge)
    fmt.Printf("%+v", req)
    fmt.Printf("%+v", reqEmptyAge)
}
// {Name:0xc000010390 Age:<nil> Weak:<nil>}{Name:0xc0000103c0 Age:0xc0000103d0 Weak:<nil>}

emmm,缺省的字段为 nil 了。

Marshal 的时候

序列化 struct 的时候,如果使用了 omitempty,也会出现类似上面反序列化的情况,对于缺省的 field 或者 zero-value,序列化得到的 JSON 数据也会缺省相关属性,此时我们也可以通过 pointer 保留相关字段,如下:

package main

import (
    "encoding/json"
    "fmt"
)

type Student struct {
    Name  string `json:"name"`
    Score int    `json:"score,omitempty"`
}

type StudentWithPointer struct {
    Name  string `json:"name"`
    Score *int   `json:"score,omitempty"`
}

func main() {
    student := Student{
        Name:  "ShanSan",
        Score: 0,
    }

    score := 0
    studentWithPointer := StudentWithPointer{
        Name:  "ShanSan",
        Score: &score,
    }

    data, _ := json.Marshal(student)
    dataWithPointer, _ := json.Marshal(studentWithPointer)
    fmt.Println(string(data))
    fmt.Println(string(dataWithPointer))
}
// {"name":"ShanSan"}
// {"name":"ShanSan","score":0}

Go Playground

参考

  • encoding/json
  • Differentiate between empty and not-set fields with JSON in Golang
  • Go''s "omitempty" explained
本文由博客一文多发平台 OpenWrite 发布!

Go json 自定义 Unmarshal 避免判断 nil

Go json 自定义 Unmarshal 避免判断 nil

腾讯《Go安全指南》中提到【必须】nil指针判断:进行指针操作时,必须判断该指针是否为nil,防止程序panic,尤其在进行结构体Unmarshal时。但如果每次使用都要判断一下是否 nil 防止 panic的话,那么这样的代码就会比较麻烦,这里我们可以使用一个自定义的方法,来避免这种情况。

使用默认的 Unmarshal 方法

package main

import (
    "encoding/json"
    "fmt"
)

type A struct {
    Name string `json:"name"`
    Num  *int   `json:"num"`
}

func main() {
    var a A
    err := json.Unmarshal([]byte(`{"name": "hsowan"}`), &a)
    if err != nil {
        panic(err)
    }
    fmt.Println(a.Name)
    // 每次使用都要判断一下是否 nil 防止 panic
    if a.Num != nil {
        fmt.Println(*a.Num)
    }
}

自定义的 Unmarshal 方法

当字段为 nil 时,在 Unmarshal 时进行初始化,这样就可以避免使用的时候发生 panic, 同时也不需要在使用的时候判断是否为 nil 了。

package main

import (
    "encoding/json"
    "fmt"
)

type A struct {
    Name string `json:"name"`
    Num  *int   `json:"num"`
}

func (a *A) UnmarshalJSON(b []byte) error {
    type alias A
    aux := (*alias)(a)
    if err := json.Unmarshal(b, &aux); err != nil {
        return err
    }
    if aux.Num == nil {
        aux.Num = new(int)
    }
    return nil
}

func main() {
    var a A
    err := json.Unmarshal([]byte(`{"name": "hsowan"}`), &a)
    if err != nil {
        panic(err)
    }
    fmt.Println(a.Name)
    fmt.Println(*a.Num)
}

参考

  • [译]自定义Go Json的序列化方法

go json 解析 Marshal 和 Unmarshal

go json 解析 Marshal 和 Unmarshal

Decoder:

package main
import (
    "encoding/json"
    "fmt"
    "io"
    "log"
    "strings"
)
func main ( ) {
    const jsonStream = `
        { "Name" : "Ed" , "Text" : "Knock knock." }
        { "Name" : "Sam" , "Text" : "Who''s there?" }
        { "Name" : "Ed" , "Text" : "Go fmt." }
        { "Name" : "Sam" , "Text" : "Go fmt who?" }
        { "Name" : "Ed" , "Text" : "Go fmt yourself!" }
    `
    type Message struct {
        Name , Text string
    }
    dec := json. NewDecoder ( strings. NewReader ( jsonStream ) )
    for {
        var m Message
        if err := dec. Decode ( & m ) ; err == io. EOF {
            break
        } else if err != nil {
            log . Fatal ( err )
        }
        fmt. Printf ( "%s: %s \n " , m. Name , m. Text )
    }
}

Marshal:

package main
import (
    "encoding/json"
    "fmt"
    "os"
)
func main ( ) {
    type ColorGroup struct {
        ID     int
        Name   string
        Colors [ ] string
    }
    group := ColorGroup {
        ID :     1 ,
        Name :   "Reds" ,
        Colors : [ ] string { "Crimson" , "Red" , "Ruby" , "Maroon" } ,
    }
    b , err := json. Marshal ( group )
    if err != nil {
        fmt. Println ( "error:" , err )
    }
    os. Stdout . Write ( b )
}

RawMessage :

package main
import (
    "encoding/json"
    "fmt"
    "log"
)
func main ( ) {
    type Color struct {
        Space string
        Point json. RawMessage // delay parsing until we know the color space
    }
    type RGB struct {
        R uint8
        G uint8
        B uint8
    }
    type YCbCr struct {
        Y   uint8
        Cb int8
        Cr int8
    }
    var j = [ ] byte ( ` [
        { "Space" : "YCbCr" , "Point" : { "Y" : 255 , "Cb" : 0 , "Cr" : - 10 } } ,
        { "Space" : "RGB" ,   "Point" : { "R" : 98 , "G" : 218 , "B" : 255 } }
    ] ` )
    var colors [ ] Color
    err := json. Unmarshal ( j , & colors )
    if err != nil {
        log . Fatalln ( "error:" , err )
    }
    for _ , c := range colors {
        var dst interface { }
        switch c. Space {
        case "RGB" :
            dst = new ( RGB )
        case "YCbCr" :
            dst = new ( YCbCr )
        }
        err := json. Unmarshal ( c. Point , dst )
        if err != nil {
            log . Fatalln ( "error:" , err )
        }
        fmt. Println ( c. Space , dst )
    }
}

Unmarshal:

package main
import (
    "encoding/json"
    "fmt"
)
func main ( ) {
    var jsonBlob = [ ] byte ( ` [
        { "Name" : "Platypus" , "Order" : "Monotremata" } ,
        { "Name" : "Quoll" ,     "Order" : "Dasyuromorphia" }
    ] ` )
    type Animal struct {
        Name  string
        Order string
    }
    var animals [ ] Animal
    err := json. Unmarshal ( jsonBlob , & animals )
    if err != nil {
        fmt. Println ( "error:" , err )
    }
    fmt. Printf ( "%+v" , animals )
}

关于json.Unmarshal将嵌套的对象编入字符串或[] byte嵌套的json怎么取值的介绍已经告一段落,感谢您的耐心阅读,如果想了解更多关于Azure 数据流:从 JSON 字符串中解析嵌套的对象列表 将对象数组解析为字符串数组分解字符串数组解析 JSON 字符串收集解析的对象重新加入原始数据结果、Go json Marshal & UnMarshal 的一点小 trick、Go json 自定义 Unmarshal 避免判断 nil、go json 解析 Marshal 和 Unmarshal的相关信息,请在本站寻找。

本文标签: