[英]Using Jackson JSON Generator, how can I write multiple objects to one field?
假設我有以下三個類(為了簡潔省略了getter和setter):
@JsonAutoDetect
public class InfoCollection{
private InfoType1 info1;
private InfoType2 info2;
}
@JsonAutoDetect
public class InfoType1{
private String fieldA;
}
@JsonAutoDetect
public class InfoType2{
private String fieldB;
}
我正在嘗試編寫一個JsonSerializer.serialize()
函數,該函數以這種格式序列化InfoCollection
對象:
{
"allInfo":{
"fieldA":"foo",
"fieldB":"bar"
}
}
這就是我現在擁有的:
jsonGenerator.writeStartObject();
jsonGenerator.writeFieldName("allInfo");
jsonGenerator.writeObject(myInfoCollection.getInfo1());
jsonGenerator.writeObject(myInfoCollection.getInfo2());
jsonGenerator.writeEndObject();
這導致以下異常:
org.codehaus.jackson.JsonGenerationException: Can not start an object, expecting field name
我錯過了一些小事情,還是我完全錯誤地采取了這種做法?
注意:到目前為止,提出的一些解決方案涉及編寫InfoType1
和InfoType2
每個字段。 我正在尋找一個不需要這個的解決方案,因為我想在具有許多領域的大型類上使用該解決方案。
您應該調用writeObjectFieldStart("allInfo")
而不是調用writeFieldName("allInfo")
,因為“allInfo”是另一個JSON對象。 因此,您的自定義序列化程序應該采用以下方式:
public void serialize(InfoCollection infoCollection, JsonGenerator jgen, SerializerProvider provider) throws IOException{
jgen.writeStartObject();
jgen.writeObjectFieldStart("allInfo");
jgen.writeObjectField("fieldA", infoCollection.getInfo1().getFieldA());
jgen.writeObjectField("fieldB", infoCollection.getInfo2().getFieldB());
jgen.writeEndObject();
jgen.writeEndObject();
}
或者您可以嘗試基於注釋的方法:
@JsonRootName("allInfo")
public class InfoCollection {
@JsonUnwrapped
private InfoType1 info1;
@JsonUnwrapped
private InfoType2 info2;
/* getters, setters */
}
(您需要啟用SerializationConfig.Feature.WRAP_ROOT_VALUE
功能才能使其正常工作。請參閱序列化功能 )
將來,當您有堆棧跟蹤時,請告訴我們問題出現在哪一行。
也就是說,修復可能是:
jsonGenerator.writeStartObject();
jsonGenerator.writeFieldName("allInfo");
jsonGenerator.writeStartObject(); // start nested object
jsonGenerator.writeFieldName("fieldA"); // start field
jsonGenerator.writeObject(myInfoCollection.getInfo1().fieldA);
jsonGenerator.writeFieldName("fieldB"); // start fieldB
jsonGenerator.writeObject(myInfoCollection.getInfo2().fieldB);
jsonGenerator.writeEndObject(); // end nested object
jsonGenerator.writeEndObject();
使用包裝器對象的解決方案:
@JsonAutoDetect
public class Wrapper {
private transient InfoCollection data; // transient makes Jackson ignore this
public String getFieldA() { return data.info1.fieldA; }
public String getFieldB() { return data.info1.fieldB; }
}
這讓傑克遜只看到你想要的東西以及你想要的東西。
或者,使用反射以遞歸方式收集所有字段及其名稱:
List<Pair<String, Object>> data = collectFields( myInfoCollection );
collectFields
應檢查所有字段並將所有內容添加到列表中,該列表可以是基元,也可以是field.getType().getName().startsWith("java.lang")
或您需要的任何其他規則。
如果該字段是引用,則遞歸調用collectFields()
。
當你有列表時,只需在循環中調用jsonGenerator
來編寫結果。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.