如何告诉Jackson在反序列化时忽略空对象?

12

在反序列化过程中(据我了解,这是将JSON数据转换为Java对象的过程),我该如何告诉Jackson,当它读取一个不包含任何数据的对象时,应该忽略它?

我正在使用Jackson 2.6.6和Spring 4.2.6。

由我的控制器接收的JSON数据如下:

{
    "id": 2,
    "description": "A description",
    "containedObject": {}
}

问题在于“containedObject”对象被直接解释并实例化。因此,一旦控制器读取此JSON数据,它就会生成一个ContainedObject对象类型的实例,但我需要它为空而不是非空。

最简单和最快速的解决方案是,在接收到的JSON数据中,将该值设为null,如下所示:

 {
        "id": 2,
        "description": "A description",
        "containedObject": null
    }

但是由于我无法控制发送给我的JSON数据,所以这是不可能的。

是否有一种像这里解释的注释(https://dev59.com/zGQo5IYBdhLWcg3wZelg)可以用于反序列化过程,并且在我的情况下可能会有帮助?

我留下我的类的表示以获取更多信息:

我的实体类如下:

public class Entity {
    private long id;
    private String description;
    private ContainedObject containedObject;

//Contructor, getters and setters omitted

}

我的包含对象类如下:

public class ContainedObject {
    private long contObjId;
    private String aString;

//Contructor, getters and setters omitted

}
3个回答

10

我会使用JsonDeserializer。检查相关字段,确定它是否为empty,如果是,则返回null,这样你的ContainedObject将为空。

类似这样(半伪代码):

 public class MyDes extends JsonDeserializer<ContainedObject> {

        @Override
        public String deserialize(JsonParser jsonParser, DeserializationContext context) throws IOException, JsonProcessingException {
            //read the JsonNode and determine if it is empty JSON object
            //and if so return null

            if (node is empty....) {
                return null;
            }
            return node;
        }

    }

那么在您的模型中:

 public class Entity {
    private long id;
    private String description;

    @JsonDeserialize(using = MyDes.class)
    private ContainedObject containedObject;

   //Contructor, getters and setters omitted

 }

希望这能帮到你!


如果我仍然找不到一个能够完成工作的注释,那么这将是我的解决方案。谢谢! - Mauricio Campagner
这是我广泛使用的解决方案。据我所知,没有任何注释可以像这个反序列化器一样实现你想要的功能。 - Mechkov
@MauricioCampagner 不要忘记接受对你的问题最有用的答案。谢谢。 - Mechkov

3
您可以按照以下步骤实现自定义反序列化器:
public class Entity {
    private long id;
    private String description;
    @JsonDeserialize(using = EmptyToNullObject.class)
    private ContainedObject containedObject;

//Contructor, getters and setters omitted

}


public class EmptyToNullObject extends JsonDeserializer<ContainedObject> {

  public ContainedObject deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
    JsonNode node = jp.getCodec().readTree(jp);
    long contObjId = (Long) ((LongNode) node.get("contObjId")).numberValue();
    String aString = node.get("aString").asText();
    if(aString.equals("") && contObjId == 0L) {
      return null;
    } else {
      return new ContainedObject(contObjId, aString);
    }

  }
}

我尝试了这个,但它不起作用。我认为这是因为该字段已知,但为空,所以Jackson不会忽略它。无论如何,谢谢。 - Mauricio Campagner
我认为这个答案和Mechkov的答案是等价的。我已经使用了两种方法,现在我更喜欢@JsonDeserialize,因为它不需要扩展JsonDeserializer。 - Christine
我编辑后意识到他的答案。他很早就回答了。你应该接受他的答案。 - M S
如何使其适用于任何类型,而不仅仅是ContainedObject? - WeGa

1

方法一:这是最常用的方法。@JsonInclude 用于排除具有空/ null/ 默认值的属性。根据您的要求使用 @JsonInclude(JsonInclude.Include.NON_NULL) 或 @JsonInclude(JsonInclude.Include.NON_EMPTY)。

    @JsonInclude(JsonInclude.Include.NON_NULL)
    public class Employee {

        private String empId;
        private String firstName;

        @JsonInclude(JsonInclude.Include.NON_NULL)
        private String lastName;
        private String address;
        private String emailId;

   }

关于Jackson注释的更多信息:https://github.com/FasterXML/jackson-annotations/wiki/Jackson-Annotations

方法2:GSON

使用GSON(https://code.google.com/p/google-gson/


5
@JsonInclude注解不起作用。根据文档,此注解仅用于序列化过程。方法2很有帮助,但我想知道是否有一种使用Jackson注解的方式来实现此功能。 - Mauricio Campagner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接