在Go中处理空的JSON数组可以使用结构体。

huangapple go评论68阅读模式
英文:

Handling Null JSON Array in Go using struct

问题

我们在golang中使用结构体,在追加结构体后得到null值。
以下是我在golang中的一部分代码,包含结构体:

type XmloutRoomRate struct {	
    CancellationPolicy Policies `bson:"cancellationPolicy" json:"cancellationPolicy"`
}

type Policies struct {
    Policies []RoomPolicies `bson:"policies" json:"policies"`
}

type RoomPolicies struct {
    Amount            float64 `bson:"amount" json:"amount"`
    DaysBeforeCheckIn int     `bson:"daysBeforeCheckIn" json:"daysBeforeCheckIn"`
} 

cancelPolicyMain := Policies{}
cancelPolicy := RoomPolicies{}

if cancelAmount < 0 {
    cancelPolicy.Amount = cancelAmount
    cancelPolicy.DaysBeforeCheckIn = cancelDay
    cancelPolicyMain.Policies = append(cancelPolicyMain.Policies, cancelPolicy)
} else {
    cancelPolicyMain = agodaPolicies{}
    cancelPolicyMain.Policies = append(cancelPolicyMain.Policies)
}

当数据存在时,得到正确的数据结构:

"cancellationPolicy": {
    "policies": [
        {
            "amount": 5141.58,
            "daysBeforeCheckIn": 5
        }
    ]
}

但是当数据不存在时,得到带有null值的结构体:

"cancellationPolicy": {
    "policies": null
}

我们希望得到的实际输出是空数组 []:

"cancellationPolicy": {
    "policies": []
}
英文:

we have struct and getting null after append struct in golang.
Find below struct with my some part of code in golang.

type XmloutRoomRate struct {	
CancellationPolicy Policies `bson:&quot;cancellationPolicy&quot; json:&quot;cancellationPolicy&quot;`
}


type Policies struct {
	Policies []RoomPolicies `bson:&quot;policies&quot; json:&quot;policies&quot;`
}


type RoomPolicies struct {
	Amount            float64 `bson:&quot;amount&quot; json:&quot;amount&quot;`
	DaysBeforeCheckIn int     `bson:&quot;daysBeforeCheckIn&quot; json:&quot;daysBeforeCheckIn&quot;`
} 

cancelPolicyMain := Policies{}
cancelPolicy := RoomPolicies{}

if cancelAmount &lt; 0 {
  cancelPolicy.Amount = cancelAmount
  cancelPolicy.DaysBeforeCheckIn = cancelDay
  cancelPolicyMain.Policies = append(cancelPolicyMain.Policies, cancelPolicy)
}else{
  cancelPolicyMain = agodaPolicies{}
  cancelPolicyMain.Policies = append(cancelPolicyMain.Policies)
}

when data present getting proper data structure.

&quot;cancellationPolicy&quot;: {
   &quot;policies&quot;: [
                {
                  &quot;amount&quot;: 5141.58,
                  &quot;daysBeforeCheckIn&quot;: 5
                }
              ]
}

But when data not available getting struct with null value.

&quot;cancellationPolicy&quot;: {
            &quot;policies&quot;: null
           }

We need my actual output with blank array [].

&quot;cancellationPolicy&quot;: {
            &quot;policies&quot;: []
           }

答案1

得分: 4

nil切片值被编组为JSON的null值。这在json.Marshal()中有记录:

> 数组和切片值被编码为JSON数组,除了[]byte被编码为base64编码的字符串,而**nil切片被编码为null的JSON值**。

nil的空切片被编组为空的JSON数组。所以只需将Policies.Policies初始化为非nil的空切片,输出中它将是[]

cancelPolicyMain = Policies{Policies: []RoomPolicies{}}

测试代码:

const cancelDay = 1

for cancelAmount := -500.0; cancelAmount &lt;= 501; cancelAmount += 1000 {
	cancelPolicyMain := Policies{}
	cancelPolicy := RoomPolicies{}

	if cancelAmount &lt; 0 {
		cancelPolicy.Amount = cancelAmount
		cancelPolicy.DaysBeforeCheckIn = cancelDay
		cancelPolicyMain.Policies = append(cancelPolicyMain.Policies, cancelPolicy)
	} else {
		cancelPolicyMain = Policies{Policies: []RoomPolicies{}}
		cancelPolicyMain.Policies = append(cancelPolicyMain.Policies)
	}

	x := XmloutRoomRate{cancelPolicyMain}
	if err := json.NewEncoder(os.Stdout).Encode(x); err != nil {
		panic(err)
	}
}

输出结果(在Go Playground上尝试):

{&quot;cancellationPolicy&quot;:{&quot;policies&quot;:[{&quot;amount&quot;:-500,&quot;daysBeforeCheckIn&quot;:1}]}}
{&quot;cancellationPolicy&quot;:{&quot;policies&quot;:[]}}
英文:

nil slice values are marshaled into JSON null values. This is documented at json.Marshal():

> Array and slice values encode as JSON arrays, except that []byte encodes as a base64-encoded string, and a nil slice encodes as the null JSON value.

Non-nil empty slices are marshaled into empty JSON arrays. So simply initialize Policies.Policies to a non-nil empty slice, and it will be [] in the output:

cancelPolicyMain = Policies{Policies: []RoomPolicies{}}

Test code:

const cancelDay = 1

for cancelAmount := -500.0; cancelAmount &lt;= 501; cancelAmount += 1000 {
	cancelPolicyMain := Policies{}
	cancelPolicy := RoomPolicies{}

	if cancelAmount &lt; 0 {
		cancelPolicy.Amount = cancelAmount
		cancelPolicy.DaysBeforeCheckIn = cancelDay
		cancelPolicyMain.Policies = append(cancelPolicyMain.Policies, cancelPolicy)
	} else {
		cancelPolicyMain = Policies{Policies: []RoomPolicies{}}
		cancelPolicyMain.Policies = append(cancelPolicyMain.Policies)
	}

	x := XmloutRoomRate{cancelPolicyMain}
	if err := json.NewEncoder(os.Stdout).Encode(x); err != nil {
		panic(err)
	}
}

Output (try it on the Go Playground):

{&quot;cancellationPolicy&quot;:{&quot;policies&quot;:[{&quot;amount&quot;:-500,&quot;daysBeforeCheckIn&quot;:1}]}}
{&quot;cancellationPolicy&quot;:{&quot;policies&quot;:[]}}

答案2

得分: 0

在数组中,“null”条目的含义很明确:它表示该数组条目缺失。

在对象(也称为字典)中,有不同的方法来表示“无条目”:可能没有该键。或者该键可能存在,但值为空数组。或者该键可能存在,但值为“null”。

您确实需要数据提供者和客户端处理之间的协议,明确每个情况的含义。由于往往很难改变数据提供者的做法,您需要将接收到的数据转换为所需的形式。

因此,您必须决定如果“policies”作为键不存在,或者存在但值为null,它们的含义是什么。我见过一些软件不会生成只有一个元素的数组,而是提供单个元素。因此,“policies”:{“amount”:...,“daysBeforeCheckin”:...}也是可能的。您可以决定接受什么,将什么视为数组,并将接收到的形式转换为所需的形式。

英文:

In an array, the meaning of a "null" entry is clear: It means this array entry is missing.

In an object aka dictionary, there are different ways to indicate "no entry": The key might not be there. Or the key might not be there, but with an empty array as value. Or the key might be there, but with a "null" value.

You really need agreement between the provider of the data and the client processing it, what each of these mean. And since it's often hard to change what the data provider does, translate what you get into what you need.

So you have to decide what it means if "policies" does not exist as a key, or if it exists as a null value. I've seen software that wouldn't produce arrays with one element, but would provide the single element instead. So "policies": { "amount": ..., "daysBeforeCheckin": ... } would also be possible. You decide what you accept, what you treat as an array, and how you change from the form you got to the form you want.

huangapple
  • 本文由 发表于 2021年10月21日 21:36:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/69663010.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定