dongxing2030 2018-06-01 11:08
浏览 154
已采纳

在Golang中处理JSON继承

I have a Java code that handles json inheritance the code is like this :

public class BaseMessage {
    private String messageId;
    private Integer type;
    ...
}

public class TextMessage  extends BaseMessage {
    private String recipient;
    private String sender;
    ...
}

public class SystemTextMessage  extends BaseMessage {
    private String field1;
    private String field2;
    ...
}

And some other classes

And I'm using Gson library like this:

    RuntimeTypeAdapterFactory<BaseMessage> runtimeTypeAdapterFactory = RuntimeTypeAdapterFactory
            .of(BaseMessage.class, "type")
            .registerSubtype(TextMessage.class,
                    String.valueOf(MessageType.TEXT_MESSAGE))
            .registerSubtype(SystemTextMessage.class,
                    String.valueOf(MessageType.SYSTEM_MESSAGE))
            ;

Gson gson = new GsonBuilder().registerTypeAdapterFactory(runtimeTypeAdapterFactory).create();
Type listType = new TypeToken<List<BaseMessage>>(){}.getType();
List<BaseMessage> list = gson.fromJson(json, listType);

And then I just iterate through the List and comparing by "instanceof".

And what about golang? Is there any way to do same thing? I failed to find something similar. Any 1 can help? Thank you.

  • 写回答

2条回答 默认 最新

  • duanbishai5271 2018-06-01 12:08
    关注

    Without using any external library, you could do:

    package main
    
    import (
        "encoding/json"
        "fmt"
        "reflect"
    )
    
    type BaseMessage struct {
        MessageId string `json:"messageId"`
        Type      int    `json:"type"`
    }
    
    type TextMessage struct {
        *BaseMessage
        Field1 string `json:"field1"`
        Field2 string `json:"field2"`
    }
    
    type SystemTextMessage struct {
        *BaseMessage
        Field1 string `json:"field1"`
        Field2 string `json:"field2"`
    }
    
    func parseJson(input []byte) []interface{} {
        var raw []map[string]interface{}
    
        json.Unmarshal(input, &raw)
        var elements []interface{}
        for _, element := range raw {
            typeId := int(element["type"].(float64))
    
            base := &BaseMessage{
                MessageId: element["messageId"].(string),
                Type:      typeId,
            }
            switch typeId {
            case 1:
                elements = append(elements, &TextMessage{base, element["field1"].(string), element["field2"].(string)})
                break
            case 2:
                elements = append(elements, &SystemTextMessage{base, element["field1"].(string), element["field2"].(string)})
                break
            }
        }
    
        return elements
    }
    
    func main() {
        input := []byte(`
                 [{
                   "messageId": "text",
                   "type": 1,
                   "field1": "field 1",
                   "field2": "field 2"
                 }, {
                   "messageId": "system",
                   "type": 2,
                   "field1": "field 1",
                   "field2": "field 2"
                 }]
            `)
    
        for _, element := range parseJson(input) {
            fmt.Println(reflect.TypeOf(element))
        }
    }
    

    You can give it a try here: https://play.golang.org/p/hB8qG6oflhR

    Be careful though, the code is not handling errors.

    I'm not sure if there's a more automatic way of doing it, but I believe you have to work with bare interface{} here.

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

报告相同问题?

悬赏问题

  • ¥15 kafka 分区副本增加会导致消息丢失或者不可用吗?
  • ¥15 微信公众号自制会员卡没有收款渠道啊
  • ¥15 stable diffusion
  • ¥100 Jenkins自动化部署—悬赏100元
  • ¥15 关于#python#的问题:求帮写python代码
  • ¥20 MATLAB画图图形出现上下震荡的线条
  • ¥15 关于#windows#的问题:怎么用WIN 11系统的电脑 克隆WIN NT3.51-4.0系统的硬盘
  • ¥15 perl MISA分析p3_in脚本出错
  • ¥15 k8s部署jupyterlab,jupyterlab保存不了文件
  • ¥15 ubuntu虚拟机打包apk错误