douhuireng4407 2019-05-03 08:14
浏览 63
已采纳

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

I need to marshal/unmarshal json to struct in golang. Assume the struct is

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"`
}

The actors or payload maybe empty. The json maybe

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

or

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

If i follow the struct A design and try to marshal json with payload empty, i have to init as below

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{},
}

Which will result in below json with one empty payload struct

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

Is there any way i can generate

"payload": ""

instead of blank payload struct? Or is there any other struct design for this kind of json format? BTW i cannot pass nil to Payload struct.

  • 写回答

2条回答 默认 最新

  • dongmou2389 2019-05-03 08:28
    关注

    The json.Marshaler interface can be implemented to customize JSON encoding, and the json.Unmarshaler interface for decoding (left as an exercise for the reader):

    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": ""
    //   }
    // }
    

    Try it on the playground: https://play.golang.org/p/9jhSWnKTnTf

    The ad-hoc _payload type is required to prevent recursion. If one would write return json.Marshal(p), the json package would call MarshalJSON again, because p is of type payload, and payload implements json.Marshaler.

    The _payload type has the same underlying type as payload but does not implement json.Marshaler (see Type definitions for details), so it is encoded using the standard rules of the json package; it produces exactly the same output that encoding a value of type payload would produce if payload didn't implement json.Marshaler.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥40 复杂的限制性的商函数处理
  • ¥15 程序不包含适用于入口点的静态Main方法
  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码