我有一個請求主體,它是一個 json 物件陣列,例如,
{
"data": [
{
"id": "1234",
"someNestedObject": {
"someBool": true,
"randomNumber": 488
},
"timestamp": "2021-12-13T02:43:44.155Z"
},
{
"id": "4321",
"someNestedObject": {
"someBool": false,
"randomNumber": 484
},
"timestamp": "2018-11-13T02:43:44.155Z"
}
]
}
我想獲取陣列中物件的計數并將它們拆分為單獨的 json 輸出以傳遞給下一個服務。我通過解組原始 json 請求正文然后回圈遍歷重新編組每個元素并將其附加到正在發送的任何傳出訊息來執行此操作。就像是,
requestBodyBytes := []bytes(JSON_INPUT_STRING)
type body struct {
Foo []json.RawMessage `json:"foo"`
}
var inputs body
_ = json.Unmarshal(requestBodyBytes, &inputs)
for input := range inputs {
re, _ := json.Marshal(m)
... do something with re
}
我看到的是前后的位元組陣列是不同的,即使字串表示是相同的。我想知道是否有一種方法可以做到這一點而不改變編碼或這里發生的任何事情來改變位元組以防止任何不需要的突變?陣列中的實際 json 物件都將具有不同的形狀,因此我無法使用帶有欄位驗證的結構化 json 定義來提供幫助。
此外,上面的代碼只是發生了什么的一個例子,所以如果有拼寫或語法錯誤,請忽略它們,因為實際代碼按照描述的方式作業。
uj5u.com熱心網友回復:
如果使用json.RawMessage,JSON 源文本將不會被決議,而是按原樣存盤在其中(它是 a []byte)。
因此,如果您想分發相同的 JSON 陣列元素,則無需對其進行任何操作,您可以按原樣“移交”它。您不必將其傳遞給json.Marshal(),它已經是 JSON 編組文本。
所以只需這樣做:
for _, input := range inputs.Foo {
// input is of type json.RawMessage, and it's already JSON text
}
如果您將 a 傳遞json.RawMessage給json.Marshal(),它可能會被重新編碼,例如壓縮(這可能會導致不同的位元組序列,但它會保存與 JSON 相同的資料)。
壓縮甚至可能是一個好主意,因為從原始背景關系(物件和陣列)中取出原始縮進可能看起來很奇怪,而且它會更短。要簡單地壓縮 JSON 文本,您可以這樣使用json.Compact():
for _, input := range inputs.Foo {
buf := &bytes.Buffer{}
if err := json.Compact(buf, input); err != nil {
panic(err)
}
fmt.Println(buf) // The compacted array element value
}
如果您不想壓縮它,而是自己縮進陣列元素,請json.Indent()像這樣使用:
for _, input := range inputs.Foo {
buf := &bytes.Buffer{}
if err := json.Indent(buf, input, "", " "); err != nil {
panic(err)
}
fmt.Println(buf)
}
使用您的示例輸入,這是第一個陣列元素的樣子(原始、壓縮和縮進):
Orignal:
{
"id": "1234",
"someNestedObject": {
"someBool": true,
"randomNumber": 488
},
"timestamp": "2021-12-13T02:43:44.155Z"
}
Compacted:
{"id":"1234","someNestedObject":{"someBool":true,"randomNumber":488},"timestamp":"2021-12-13T02:43:44.155Z"}
Indented:
{
"id": "1234",
"someNestedObject": {
"someBool": true,
"randomNumber": 488
},
"timestamp": "2021-12-13T02:43:44.155Z"
}
試試Go Playground上的示例。
另請注意,如果您決定壓縮或縮進回圈中的單個陣列元素,您可以bytes.Buffer在回圈之前創建一個簡單的,并在每次迭代中重用它,呼叫它的Buffer.Reset()方法來清除前一個陣列的資料。
它可能看起來像這樣:
buf := &bytes.Buffer{}
for _, input := range inputs.Foo {
buf.Reset()
if err := json.Compact(buf, input); err != nil {
panic(err)
}
fmt.Println("Compacted:\n", buf)
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/405670.html
標籤:
