2016-09-15 38 views
1

我試圖用任意對象作爲序列化/反序列化Map<?, ?> Jackson版本2.8。該JSON對方應該是夫妻的陣列,即給定如何反序列化與傑克遜的地圖<?, ?>?

public class Foo { 
    public String foo; 
    public Foo(String foo) { 
     this.foo = foo; 
    } 
} 

public class Bar { 
    public String bar; 
    public Bar(String bar) { 
     this.bar = bar; 
    } 
} 

然後

Map<Foo, Bar> map; 
map.put(new Foo("foo1"), new Bar("bar1")); 
map.put(new Foo("foo2"), new Bar("bar2")); 

應此JSON

[ 
    [ { "foo": "foo1" }, { "bar": "bar1" } ], 
    [ { "foo": "foo2" }, { "bar": "bar2" } ] 
] 

所以我做了串行一部分

表示
public class MapToArraySerializer extends JsonSerializer<Map<?, ?>> { 

    @Override 
    public void serialize(Map<?, ?> value, JsonGenerator gen, SerializerProvider serializers) 
     throws IOException, JsonProcessingException { 
     gen.writeStartArray(); 
     for (Map.Entry<?, ?> entry : value.entrySet()) { 
      gen.writeStartArray(); 
      gen.writeObject(entry.getKey()); 
      gen.writeObject(entry.getValue()); 
      gen.writeEndArray(); 
     } 
     gen.writeEndArray(); 
    } 

} 

但我有不知道如何寫JsonDeserializer來做相反的工作。有什麼建議麼?

注:我需要[ [ "key1", "value1" ], [ "key2", "value2" ] ]符號能夠消耗該JSON在JavaScript中new Map(...)JSON.stringify(map)會產生過多的符號(見https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Map)。爲了澄清,這樣的地圖將是其他類的地域,例如,

public class Baz { 

    @JsonSerialize(using = MapToArraySerializer.class) 
    @JsonDeserialize(using = ArrayToMapDeserializer.class, keyAs = Foo.class, contentAs = Bar.class) 
    Map<Foo, Bar> map; 

} 

ArrayToMapDeserializer extends JsonDeserializer<Map<?, ?>>是我尋求幫助的地方。

+0

我認爲你是在複雜的。你的JSON不是地圖。你爲什麼使用'Map'來表示它? 'Foo'和'Bar'有任何使它們不同的屬性嗎? –

+0

在實際使用情況下,'Foo'和'Bar'是複雜的對象,具有'Foo'作爲鍵類型的映射可能是另一個對象的字段。我需要將這個Java地圖移植到JavaScript中,JavaScript有它自己的'Map',它以這種形式序列化(請參閱問題中的MDN鏈接)。 –

+0

是的,它們可能是完全不同的對象(任何Java對象)。我已經更新了這個問題來說明問題。 –

回答

3

我想出了這個解決方案:

public class ArrayToMapDeserializer extends JsonDeserializer<SortedMap<Object, Object>> 
    implements ContextualDeserializer { 

    private Class<?> keyAs; 

    private Class<?> contentAs; 

    @Override 
    public Map<Object, Object> deserialize(JsonParser p, DeserializationContext ctxt) 
     throws IOException, JsonProcessingException { 
     return this.deserialize(p, ctxt, new HashMap<>()); 
    } 

    @Override 
    public Map<Object, Object> deserialize(JsonParser p, DeserializationContext ctxt, 
     Map<Object, Object> intoValue) throws IOException, JsonProcessingException { 
     JsonNode node = p.readValueAsTree(); 
     ObjectCodec codec = p.getCodec(); 
     if (node.isArray()) { 
      node.forEach(entry -> { 
       try { 
        JsonNode keyNode = entry.get(0); 
        JsonNode valueNode = entry.get(1); 
        intoValue.put(keyNode.traverse(codec).readValueAs(this.keyAs), 
         valueNode.traverse(codec).readValueAs(this.contentAs)); 
       } catch (NullPointerException | IOException e) { 
        // skip entry 
       } 
      }); 
     } 
     return intoValue; 
    } 

    @Override 
    public JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property) 
     throws JsonMappingException { 
     JsonDeserialize jsonDeserialize = property.getAnnotation(JsonDeserialize.class); 
     this.keyAs = jsonDeserialize.keyAs(); 
     this.contentAs = jsonDeserialize.contentAs(); 
     return this; 
    } 

} 

它可以這樣使用:

public class Baz { 

    @JsonSerialize(using = MapToArraySerializer.class) 
    @JsonDeserialize(using = ArrayToMapDeserializer.class, 
     keyAs = Foo.class, contentAs = Bar.class) 
    Map<Foo, Bar> map; 

} 
0

這裏是反序列化:

@Override 
public Map<?, ?> deserialize(JsonParser p, DeserializationContext ctxt) 
     throws IOException, JsonProcessingException { 
    Map map = new LinkedHashMap(); 

    ObjectCodec oc = p.getCodec(); 
    JsonNode anode = oc.readTree(p); 

    for (int i = 0; i < anode.size(); i++) { 
     JsonNode node = anode.get(i); 
     map.put(node.get(0), node.get(1)); 
    } 

    return map; 
} 

我增加了一些測試案例,用新Oson的實施,原來的解決方案,其中我用oson做轉換,但使用不同的convension:地圖JSON:{鍵:值1,鍵2:值2,...},所以JSON輸出變爲:

{ 
    { 
    "foo": "foo1" 
    }: { 
    "bar": "bar1" 
    }, 
    { 
    "foo": "foo2" 
    }: { 
    "bar": "bar2" 
    } 
} 

您可以檢查出source code

+0

我問傑克遜和一個具體的輸出,你提供了一個不同的工具和不同的輸出。請檢查:http:// stackoverflow。com/help/how-to-answer –

+0

沒有正確的配置,jackson得到這個:{「[email protected]」:{「bar」:「bar1」},「ca.oson.json。 [email protected]「:{」bar「:」bar2「}} –

+0

ArrayToMapDeserializer不應該太難實現,當我有晚上的時間我會爲你嘗試一個 –