2015-03-18 46 views
1

在我使用Spring的Web應用程序中,我們想要使用自定義的JSON結構。 Spring缺省需要這樣一個POJO:Spring框架JSON序列化到數組而不是對象

public class Model { 

    private int id; 
    private String name; 

    public Model(){} 

    public Model(int id, String name){ 
     this.id = id; 
     this.name = name; 
    } 
} 

,並把它變成這樣:

{"id":1, "name":"Bob"} 

與我們的應用,我們希望把它變成這個:

[1, "Bob"] 

我想要使用Spring的默認序列化邏輯來檢測Java類型(int,String,Collection等)並映射到適當的JSON類型,但只是將包裝對象更改爲數組而不是和對象使用fi視場。

這是迄今爲止我已經使用的序列化程序(將使用@JsonSerialize(using = Serializer.class))在模型中實現),但不希望重寫Spring已經實現的所有邏輯。

public class Serializer extends JsonSerializer<Model> { 
    @Override 
    public void serialize(Model value, JsonGenerator jgen, SerializerProvider provider) 
     throws IOException, JsonProcessingException { 

     jgen.writeStartArray(); 
     jgen.writeString(value.id); 
     .... other values ... 
     jgen.writeEndArray(); 

    } 
} 

我如何可以掛接到預先存在的串行,使這個新的串行器將與任何POJO工作作爲默認的人做(而不只是Model類,但任何類似或子類,我們需要序列化數組)?這可能具有混合屬性,並且沒有特定的屬性命名約定。

我想避免爲每個不同的Model類(...其他值...)部分編寫自定義序列化程序。

+1

串行器是正確的方法。 – 2015-03-18 21:33:35

+0

啊,是的。我需要澄清,因爲我希望序列化程序不是特定於一個Model類,而是與任何POJO一起工作並相應地動態構建數組。謝謝! – Cameron 2015-03-18 21:53:45

+1

因此,您需要'[1]',而不是'{「id」:[1]}'而不是'{「id」:1}'? – 2015-03-18 21:54:53

回答

0

Apache BeanUtils library看看,特別要注意BeanUtils.populate()方法。

該方法的作用是將任何給定的Object轉換爲基於JavaBeans約定的Map<String, Object>。在鍵中你有屬性名稱,而在值中你有每個屬性的值。這種方法對於標準情況應該足夠了。仔細閱讀文檔,檢查如何處理特殊情況。

Model model = ...; // get your model from some place 

Map<String, Object> properties = new HashMap<>(); 

BeanUtils.populate(model, properties); 

// Exception handling and special cases left as an excercise 

以上遞歸地填補了properties地圖,也就是說,如果你的Model有一個屬性名爲otherModel類型爲OtherModel,那麼properties地圖會有另一個地圖在該otherModel鍵相匹配的條目,等等對於其他嵌套POJO。

一旦你有properties地圖,你想要序列化爲你的數組元素將在其值。所以,這樣的事情應該做的工作:

public List<Object> toArray(Map<String, Object> properties) { 
    List<Object> result = new ArrayList<>(); 

    for (Object obj : properties.values()) { 
     Object elem = null; 
     if (obj != null) { 
      Class<?> clz = obj.getClass(); 
      if (Map.class.isAssignableFrom(clz)) { 
       elem = toArray((Map<String, Object>) obj); // recursion! 
      } else { 
       elem = obj; 
      } 
     } 
     result.add(elem); // this adds null values 
          // move 1 line up if you don't 
          // want to serialize nulls 
    } 
    return result; 
} 

然後調用toArray()方法之後,你就會有一個List<Object>準備使用標準的彈簧機構序列化。我甚至相信你將不再需要特定的串行:

List<Object> array = toArray(properties); 
return array; // return this array, i.e. from a Controller 

免責聲明:

請以此爲指導,而不是作爲一個最終的解決方案。我試圖儘可能小心,但代碼可能有錯誤。我很確定它需要特殊處理陣列和POJO的Iterable。毫無疑問,缺乏異常處理。它僅適用於POJO。如果提供的對象具有循環引用,它可能會爆炸。它沒有測試!

0

您可以使用@JsonValue註釋。 例子:

public class Model { 

    private int id; 

    public Model(){} 

    public Model(int id){ 
    this.id = id; 
    } 

    @JsonValue 
    public int[] getValue() { 
    return new int[]{this.id}; 
    } 
} 
+0

這將工作的一個具體實例。我已經更新了這個問題,以澄清我正在尋找更通用的解決方案。謝謝! – Cameron 2015-03-18 22:31:47

+0

在這種情況下,我會使用mixin註釋(http://wiki.fasterxml.com/JacksonMixInAnnotations)。您可以創建一個接口(或抽象類),並使用用'@ JsonValue'註釋的value方法,並在所有類中實現這個mixin接口。此外,你可以在ObjectMapper的配置中指定這個mixin,並且實際上不會改變你自己的類。 – Advanced 2015-03-19 23:53:14

相關問題