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 metadata提取的PDF元数据,如何转换为一个Excel
  • ¥15 关于arduino编程toCharArray()函数的使用
  • ¥100 vc++混合CEF采用CLR方式编译报错
  • ¥15 coze 的插件输入飞书多维表格 app_token 后一直显示错误,如何解决?
  • ¥15 vite+vue3+plyr播放本地public文件夹下视频无法加载
  • ¥15 c#逐行读取txt文本,但是每一行里面数据之间空格数量不同
  • ¥50 如何openEuler 22.03上安装配置drbd
  • ¥20 ING91680C BLE5.3 芯片怎么实现串口收发数据
  • ¥15 无线连接树莓派,无法执行update,如何解决?(相关搜索:软件下载)
  • ¥15 Windows11, backspace, enter, space键失灵