簡體   English   中英

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

[英]Partial JSON serialisation/de-serialization using 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"
}

除非您存儲有關原始 JSON 對象中存在哪些字段的信息,否則這是不可能的。 為此,您可以在Foo周圍使用一個包裝器,其中包含一個Foo加上此附加信息。 下面是一個例子。

注意:這是偽代碼 方法和類名的一部分來自 Gson 庫,一部分是我即時發明的,但您明白了。 我認為使用 Jackson 的類來翻譯它應該不難。

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字段字段。 每種方法都有其優點和缺點。 由您決定哪一種最適合您的情況。

您可以使用@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"}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM