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 微信公众号如何开发网页
  • ¥15 h3.6m 人类行为预测论文复现
  • ¥50 wordpress项目注册报失败刷新后其实是成功状态,请求排查原因
  • ¥20 linxu服务器僵尸进程不释放,代码如何修改?
  • ¥15 pycharm激活不成功
  • ¥40 如果update 一个列名为参数的value
  • ¥15 基于51单片机的水位检测系统设计中LCD1602一直不显示
  • ¥15 OCS2安装出现问题,请大家给点意见
  • ¥15 ros小车启动launch文件报错
  • ¥15 vs2015到期想登陆但是登陆不上