如何在结构类型中处理nil结构变量

时间:2019-05-03 08:14:08

标签: go struct

我需要编组/解组json以在golang中进行构造。假设结构为

public String myMethod(@RequestParam("callbackUrl") String callBackUrl, …) {
    System.out.println(callBackUrl); //this will print the url to console
}

演员或有效载荷可能是空的。 json也许

type A struct {
  Id string `json:"id"`
  Version string `json:"version"`
  Actors []actor `json:"actors`
  Payload struct {
     Name string `json:"name"`
     Number string `json:"number"`
  }
}
type payload struct {
    Name string `json:"name"`
    Number string `json:"number"`
}
type actor struct {
    Id   string `json:"id"`
    Type string `json:"type"`
    Role string `json:"role"`
}

{
  "id": "78a07cea-be2b-499c-b82b-e4f510260484",
  "version": "1.0.0",
  "actors": [
    {
      "id": "1234567",
      "type": "XXX",
      "role": "111"
    },
    {
      "id": "7654321",
      "type": "YYY",
      "role": "222"
    }
  ],
  "payload": ""
}

如果我遵循struct A设计并尝试在有效负载为空的情况下封送json,则必须按如下所示进行初始化

{
  "id": "78a07cea-be2b-499c-b82b-e4f510260484",
  "version": "1.0.0",
  "actors": [],
  "payload": {
       "name": "XXXX",
       "number": "1234567"
   }
}

这将在json下面产生一个空的有效负载结构

a := A{
  Id: "78a07cea-be2b-499c-b82b-e4f510260484",
  Version: "1.0.0",
  Actors: []actor{
    actor{
      Id: "1234567",
      Type: "XXX",
      Role: "111",
    },
    actor{
      Id: "7654321",
      Type: "YYY",
      Role: "222",
    },
  },
  Payload: payload{},
}

有什么办法可以生成

  

“有效载荷”:“”

而不是空白的有效载荷结构?还是这种json格式还有其他结构设计吗?顺便说一句,我不能将nil传递给Payload结构。

2 个答案:

答案 0 :(得分:3)

json.Marshaler interface可以实现自定义JSON编码,而json.Unmarshaler interface可以实现解码(作为练习供读者阅读):

package main

import (
    "encoding/json"
    "fmt"
)

type A struct {
    Payload payload
}

type payload struct {
    Name   string `json:"name"`
    Number string `json:"number"`
}

func (p payload) MarshalJSON() ([]byte, error) {
    if p.Name == "" && p.Number == "" {
        return []byte(`""`), nil
    }

    type _payload payload // prevent recursion
    return json.Marshal(_payload(p))
}

func main() {
    var a A
    b, _ := json.MarshalIndent(a, "", "  ")
    fmt.Println(string(b))

    a.Payload.Name = "foo"
    b, _ = json.MarshalIndent(a, "", "  ")
    fmt.Println(string(b))
}

// Output:
// {
//   "Payload": ""
// }
// {
//   "Payload": {
//     "name": "foo",
//     "number": ""
//   }
// }

在操场上尝试:https://play.golang.org/p/9jhSWnKTnTf

需要临时_payload类型以防止递归。如果有人写return json.Marshal(p),则json包会再次调用MarshalJSON,因为p的类型为payload,而payload实现json.Marshaler。

_payload类型与payload具有相同的基础类型,但是不是实现json.Marshaler(有关详细信息,请参见Type definitions),因此已对其进行了编码使用json包的标准规则;如果payload未实现json.Marshaler,它将产生与编码类型payload的值完全相同的输出。

答案 1 :(得分:1)

检查将omitempty与json struct标签一起使用是否有帮助。我认为它将导致"payload": {}而不是"payload": ""