【问题标题】:How to map various possible types of a JSON field to a POJO attribute?如何将 JSON 字段的各种可能类型映射到 POJO 属性?
【发布时间】:2019-10-20 18:19:04
【问题描述】:

我有一个 POJO,用于映射从 rabbitmq 接收到的值。这些消息是从我无法控制的其他第三方服务发送的。问题是这些服务不会以一致的方式发送某些字段。

例如在error字段的情况下,只有当第三方服务想要发送消息通知有错误时,该字段才会有信息。某些服务可能会以这种方式将其 JSON 消息发送到队列:

{
   id: 123,
   name: "PersonA",
   error: null
}

还有一些服务可以通过这种方式发送 JSON 消息:

{
   id: 123,
   name: "PersonA",
   error: []
}

还有一些服务可能会完全省略该字段:

{
   id: 123,
   name: "PersonA"
}

当然,如果出现错误,该错误字段将包含其中的字段:

{
   id: 123,
   name: "PersonA",
   error: {
      message: "Cannot find PersonA"
   }
}

因此,错误字段有可能是nullundefinedarrayobject。 问题是,我只能在我的 POJO 中为 error 字段定义一个类型。

public class MyMessage {
    private int id;
    private MessageError error;
    private String name;

    @JsonCreator
    public MyMessage(
        @JsonProperty("id") int id,
        @JsonProperty("error") MessageError error,     // error is a MessageError object already but what is sent in could be null, undefined, an array or an object
        @JsonProperty("name") String name
    ) {
        this.id = id;
        this.error = error;
        this.name = name;
    }
}

public class MessageError {
    private String message;

    @JsonCreator
    public MessageError(
        @JsonProperty("message") String message
    ) {
        this.message = message;
    }
}

我正在与 Jackson 一起使用 Spring。 在这种情况下,当它被反序列化时,如何处理和映射可能分配给消息中 error 字段的所有可能值到 POJO?

【问题讨论】:

  • 我认为最好的方法是使用JsonNode作为error
  • 同意@Deadpool 的评论。顺便说一句,你所有的 JSON 字符串都不合法,每个字段的键名都应该用双引号括起来。

标签: java json spring jackson rabbitmq


【解决方案1】:

如果您在 json 数据中没有任何标记来识别其来源和形状,我会尝试将错误字段类型设置为对象,如果它不起作用或不适合,则设置为“json raw”正如How can I include raw JSON in an object using Jackson? 的答案中所解释的那样 因此,您可以根据您在运行时发现的内容以适当的方式处理错误字段,从上面详述的预期内容中窥视。

【讨论】:

    【解决方案2】:

    解决此问题的最简单方法是将error 字段定义为常见的Object 类型

    @JsonInclude(JsonInclude.Include.NON_NULL)
    @JsonPropertyOrder({
    "id",
    "name",
    "error"
    })
    public class MyMessage {
    
    @JsonProperty("id")
    private int id;
    @JsonProperty("name")
    private String name;
    @JsonProperty("error")
    private Object error;
    
    @JsonProperty("id")
    public int getId() {
    return id;
    }
    
    @JsonProperty("id")
    public void setId(int id) {
    this.id = id;
    }
    
    @JsonProperty("name")
    public String getName() {
    return name;
    }
    
    @JsonProperty("name")
    public void setName(String name) {
    this.name = name;
    }
    
    @JsonProperty("error")
    public Object getError() {
    return error;
    }
    
    @JsonProperty("error")
    public void setError(Object error) {
    this.error = error;
    }
    
    }
    

    然后你必须将它映射到另一个 DTO:

    // someplace where you will map it
    
    MyMessage message = source.getMessageFromQueue();
    
    if(message.getError() == null) {
      // do something
    } else {
       Object error = message.getError();
       handleError(error);
    }
    
    private void handleError(Object error) {
       if(error instanceOf MessageError) {
           handleMessageError((MessageError) error) // handle as known MessageError object 
       } else if(error instanceOf String) {
           handleStringError((String) error) // handle as String, write in logs maybe
       } else if(error instanceOf List) {
           handleErrors((String) error) // handle as List errors
       } else {
           handleUndefinedError()
       }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-20
      • 2021-11-08
      • 2019-07-01
      • 2017-02-07
      相关资源
      最近更新 更多