使用Jackson进行部分JSON序列化/反序列化

时间:2014-12-06 16:46:32

标签: java json jackson

我有一个问题,我暂时无法解决。 让我们想象一个非常简单的Java类

class Foo {
     public String bar;
     public String baz;
}

如何实现反序列化的操作以及随后的某些JSON请求的序列化实际上在部分JSON对象方面是不可变的。如果我反序列化

那么
{
    "bar": "some value",
    "baz": null
}

进入Foo实例,然后将其序列化为JSON,我得到

{
    "bar": "some value",
    "baz": null
}

如果我在没有“baz”的情况下反序列化部分JSON

{
    "bar": "some value"
}

我再次获得没有“baz”的部分JSON

{
    "bar": "some value"
}

2 个答案:

答案 0 :(得分:1)

除非您存储有关原始JSON对象中存在哪些字段的信息,否则无法进行此操作。为此,您可以使用Foo周围的包装器,其中包含Foo以及此附加信息。以下是一个例子。

注意:这是伪代码。方法和类名是Gson库的一部分,是我在飞行中发明的部分,但你明白了。我认为使用杰克逊的课程来翻译它应该不难。

class DeserializedFoo {

    private Foo foo;
    private Set<String> includedFields = new HashSet<>();

    private DeserializedFoo(){

    }

    public static class DeSerializer implements JsonDeserializer<DeserializedFoo> {
        @Override
        public DeserializedFoo deserialize(JsonElement je) {
            DeserializedFoo dsFoo = new DeserializedFoo();
            dsFoo.foo = parse(je);
            for(JsonElement prop : je.elements()){
                includedFields.add(prop.getName());
            }
            return dsFoo;
        }
    }

    public static class Serializer implements JsonSerializer<DeserializedFoo> {
        @Override
        public JsonElement serialize(DeserializedFoo dsFoo) {
            JsonElement jsonFoo = serialize(dsFoo.foo);

            // Leave only fields that were present in the JSON 
            // element from which this was deserialized.
            Iterable it = jsonFoo.elements().iterable();
            while(it.hasNext()){
                JsonElement prop = it.next();
                if(!includedFields.contains(prop.getName()){
                    it.remove();
                }
            }
            return jsonFoo;
        }
    }   
}

你当然可以使用继承而不是包装,例如通过定义class DeserilizedFoo extends Foo并添加includedFields字段。每种方法都有其优点和缺点。由你来决定最适合你的情况。

答案 1 :(得分:1)

您可以使用@JsonInclude(Include.NON_DEFAULT)和。注释您的课程 将baz属性的默认值设置为魔术字符串,该字符串表示该值不应出现在JSON中。

以下是一个例子:

public class JacksonIncludeNull {

    final static String JSON1 = "{\n" +
            "    \"bar\": \"some value\",\n" +
            "    \"baz\": null\n" +
            "}";

    final static String JSON2 = "{\n" +
            "    \"bar\": \"some value\"\n" +
            "}";

    @JsonInclude(JsonInclude.Include.NON_DEFAULT)
    static class Foo {
        public String bar;
        public String baz = "##default";

        @Override
        public String toString() {
            return "Foo{" +
                    "bar='" + bar + '\'' +
                    ", baz='" + baz + '\'' +
                    '}';
        }
    }

    public static void main(String[] args) throws IOException {
        final ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(new GuavaModule());
        final Foo foo1 = mapper.readValue(JSON1, Foo.class);
        System.out.println(JSON1);
        System.out.println("Object: " + foo1);
        System.out.println("Serialize: " + mapper.writeValueAsString(foo1));

        System.out.println();

        final Foo foo2 = mapper.readValue(JSON2, Foo.class);
        System.out.println(JSON2);
        System.out.println("Object: " + foo2);
        System.out.println("Serialize: " + mapper.writeValueAsString(foo2));
    }
}

输出:

{
    "bar": "some value",
    "baz": null
}
Object: Foo{bar='some value', baz='null'}
Serialize: {"bar":"some value","baz":null}

{
    "bar": "some value"
}
Object: Foo{bar='some value', baz='##default'}
Serialize: {"bar":"some value"}