使用Jackson忽略JSON主体中的空元素

4
我将使用Java中的Jackson库构建一个JSON数据体。它可能像以下这样:
{
   "subject": "math",
    "marks": "100",
    "student":{
        "name": "x",
        "class": "8"
    }
 }

根据不同的REST URI,必须忽略json主体中的某些字段或元素。如何使用jackson忽略上述json主体中的“student”部分?当我忽略它时,我应该只能获取到:
{ "subject": "math", "marks": "100"}

但是我得到的结果如下,这是不正确的 -
{ "subject": "math", "marks": "100","student":{}}

我有两个类,一个是主题,一个是学生,都有getter和setter。我尝试使用@JsonIgnore,但它会忽略所有的URI,而我不想这样做。我也尝试了@JsonInclude(Include.NON_EMPTY)。我该如何实现这一点?

我在这里添加了我的代码。根据不同的REST URI,JSON主体必须忽略一些字段或元素。例如,对于一个URI,它应该包含所有字段,对于另一个URI,它应该忽略学生。

    score.setSubject("math");
    score.setMarks("100");

    Score.Student student =score.new Student();
    score.setStudent(student);

    switch (type) {
    case StudentAdd:
        score.setSubject("math");
        score.setMarks("100");
        break;
    case StudentDelete:
        score.setSubject("math");
        score.setMarks("100");
        break;
    case StudentComplete:
        score.setChangeReason("C");

    default:
        break;
        score.setSubject("math");
        score.setMarks("100");

    score.setStudent(student);

    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.configure(SerializationFeature.INDENT_OUTPUT, true);
    //objectMapper.setSerializationInclusion(Include.NON_NULL);
    objectMapper.setSerializationInclusion(Include.NON_EMPTY);

    StringWriter jsonBody = new StringWriter();
    objectMapper.writeValue(jsonBody, score);

    return jsonBody.toString();
}

    //@JsonInclude(Include.NON_EMPTY)
    class Score {

        private String subject;
        private String marks;
        private Student student;

        public String getSubject() {
            return subject;
        }

        public void setSubject(String subject) {
            this.subject = subject;
        }

        public String getMarks() {
            return marks;
        }

        public void setMarks(String marks) {
            this.marks = marks;
        }

        public Student getStudent() {
            return student;
        }

        public void setStudent(Student student) {
            this.student = student;
        }

    //@JsonInclude(Include.NON_NULL)
    class Student {

        private String name;

        @JsonProperty("class")
        private String clazz;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getClazz() {
            return clazz;
        }

        public void setClazz(String clazz) {
            this.clazz = clazz;
        }

}
    }
   }
     }

可能是 Jackson Different JSONFilter same Class 的重复问题。 - toongeorges
3个回答

3

可以使用注解 JsonInclude 来进行配置,将其值设置为 NON_NULL 而不是 NON_EMPTY

关于 NON_EMPTYNON_NULL 的 Javadoc 文档并不十分清晰,但我的实验表明,在使用 Jackson 2.6.2 时,使用 NON_NULL 可以像您期望的那样工作。

@JsonProperty
@JsonInclude(Include.NON_NULL)
private Student student;

例子

ObjectMapper mapper = new ObjectMapper();
System.out.println(mapper.writeValueAsString(new Foo(100, new Student("bob"), "math")));
System.out.println(mapper.writeValueAsString(new Foo(100, null, "math")));

输出

{"marks":100,"subject":"math","student":{"name":"bob"}}
{"marks":100,"subject":"math"}

请注意,这也可以通过全局设置来完成。
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

我已经使用了NON_NULL,它对某些人有效,但对其他人无效。例如:我的原始JSON如下所示--{ "subject": "math", "marks": "100", "student":{ "name": "x", "class": "8" ,"schoolList": [{"school": "abc"}] } @JsonInclude(Include.NON_NULL) 能够忽略“schoolList”,但不能忽略“student”。 - user2266817

1

编辑

这篇文章似乎是一个重复

编辑2

使用 @JsonView 替代 @JsonFilter

以下是使用 @JsonView 打印同一 JSON 对象的不同视图的示例代码:

{"subject":"math","marks":"100"}

{"subject":"math","marks":"100","student":{"name":"x","class":"8"}}

public class Views {
    public static class Filtered {}
    public static class All extends Filtered {}
}

public class Student {
    private String name;

    @JsonProperty("class")
    private String clazz;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getClazz() {
        return clazz;
    }

    public void setClazz(String clazz) {
        this.clazz = clazz;
    }
}

public class Score {
    @JsonView(Views.Filtered.class)
    private String subject;

    @JsonView(Views.Filtered.class)
    private String marks;

    @JsonView(Views.All.class)
    private Student student;

    public String getSubject() {
        return subject;
    }

    public void setSubject(String subject) {
        this.subject = subject;
    }

    public String getMarks() {
        return marks;
    }

    public void setMarks(String marks) {
        this.marks = marks;
    }

    public Student getStudent() {
        return student;
    }

    public void setStudent(Student student) {
        this.student = student;
    }
}

public class JsonTest {
    public static void main(String[] args) throws JsonProcessingException {
        Student student = new Student();
        student.setName("x");
        student.setClazz("8");

        Score score = new Score();
        score.setSubject("math");
        score.setMarks("100");
        score.setStudent(student);

        ObjectMapper mapper = new ObjectMapper();

        //do not serialize student property
        System.out.println(mapper.writerWithView(Views.Filtered.class).writeValueAsString(score));

        //also serialize student property
        System.out.println(mapper.writeValueAsString(score));
    }
}

感谢您的回复。上面的答案有效。但我正在寻找一种根据请求的URI更改JSON主体的方法。例如,对于一个URI,我需要在JSON主体中包括学生和分数的所有内容,对于另一个URI,我需要排除学生。我已经编辑了我的问题并附上了我的代码。 - user2266817
我不太明白你的评论。我已经更改了代码,使用 @JsonView 替代 @JsonFilter,这将导致更清晰的代码。我假设每个 URI 都绑定到一个 Web 服务方法。这些方法可以各自使用不同的视图? - toongeorges

0

在您的ObjectMapper中将WRITE_NULL_MAP_VALUES设置为false。

代码:

    ObjectMapper mapper = new ObjectMapper();
    mapper.configure(SerializationConfig.Feature.WRITE_NULL_MAP_VALUES, false);

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