編集:あなたの何人かの要求により、私は私の実際のデータ構造とクラスを投稿しています。私はあなたが問題を理解しやすくすることに失敗しました。
null
Jackson JSON配列要素の解決に問題があり、この投稿の後半で報告する例外が発生します。
サードパーティプロバイダーからの長いJSON文字列があります。
[
null,
null,
[
{
"t" : {
"id" : 0,
"it" : "Attuazione"
},
"c" : "DM.10.0.2",
"l" : "Macro 2",
"v0" : 0,
"scid" : "1",
"m" : "10",
"sam" : 0,
"v1" : 100,
"smcm" : true,
"w" : "OD.10.4",
"st" : {
"auto_formula" : {
"ia" : "($x > 0 ? 1 : 0)",
"id" : "($x > 0 ? 1 : 0)",
"bit" : "($x > 0 ? 1 : 0)",
"oa" : "($x > 0 ? 1 : 0)",
"od" : "($x > 0 ? 1 : 0)",
"dm" : "($x > 0 ? 1 : 0)"
},
"id" : 0,
"css_rule" : "containerTypeOnOff",
"default_measure_unit" : null,
"it" : "On \/ Off",
"widget" : {
"id" : 0,
"caption" : {
"it" : "Etichetta di testo"
}
}
}
}
],
null,
null,
null,
null,
null
]
私のJavaクラスアンサンブルは次のとおりです。
これは最も外側のコンテナです。
public class TinyMap {
ArrayList<TinyMapModule> modules;
public TinyMap() { ... }
public ArrayList<TinyMapModule> getModules() { ... }
/**
* @param modules the modules to set
*/
@SuppressWarnings("unchecked")
public void setModules(ArrayList<TinyMapModule> modules) { ... }
public void appendNewMacro(TinyMapModule m) { ... }
}
そして、これは第1レベルのコンテナです。
public class TinyMapModule {
private ArrayList<TinyMapMacro> macros;
/**
* C'tor
*/
public TinyMapModule() { ... }
/**
* @return ArrayList<TinyMapMacro>
*/
public ArrayList<TinyMapMacro> getMacros() { ... }
/**
* @param macros the macros to set
*/
@SuppressWarnings("unchecked")
public void setMacros(ArrayList<TinyMapMacro> macros) { ... }
}
そして、これは最も内側のレベルです:
public class TinyMapMacro {
private String c;
private String l;
private String m;
private MacroType t;
private String w;
private static Logger logger;
static {
logger = Logger.getLogger(TinyMapMacro.class);
DOMConfigurator.configure("log4j.xml");
}
/**
* C'tor
*/
public TinyMapMacro() { ... }
public static class MacroType {
private int id;
private String it; // Italian
public int getId() { ... }
public void setId(int id) { ... }
public String getIt() { ... }
public void setIt(String it) { ... }
}
public String getC() { ... }
public void setC(String c) { ... }
public String getL() { ... }
public void setL(String l) { ... }
public String getM() { ... }
public void setM(String m) { ... }
public MacroType getT() { ... }
public void setT(MacroType t) { ... }
public String getW() { ... }
public void setW(String w) { ... }
public int getTypeId() { ... }
public String getLocalizedTypeString() { ... }
}
最後に、これは私の逆シリアル化コードです:
ObjectMapper mapper = new ObjectMapper();
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
mapper.disable(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES);
ObjectReader reader = mapper.reader(TinyMapModule.class);
try {
logger.info("Instantiating ObjectMapper");
TinyMap tm = new TinyMap();
tm.buildTinyMap(reader.readValues(jsonString.replaceAll("null", "[{\"name\":\"\"}]")));
for (int i = 0; i < tm.getModules().size(); i++) {
if (tm.getModules().get(i) == null)
continue;
for (int j = 0; j < tm.getModules().get(i).getMacros().size(); j++) {
if (tm.getModules().get(i).getMacros().get(j) == null)
continue;
System.out.println(String.format("c: %s", tm.getModules().get(i).getMacros().get(i).getC()));
System.out.println(String.format("l: %s", tm.getModules().get(i).getMacros().get(i).getL()));
System.out.println(String.format("m: %s", tm.getModules().get(i).getMacros().get(i).getM()));
System.out.println(String.format("t.id: %d", tm.getModules().get(i).getMacros().get(i).getTypeId()));
System.out.println(String.format("t.it: %s", tm.getModules().get(i).getMacros().get(i).getLocalizedTypeString()));
System.out.println(String.format("w: %s", tm.getModules().get(i).getMacros().get(i).getW()));
}
}
logger.info("Execution terminated");
}
...
極端な統合では、問題を次のように図式化しようとしました。
TinyMap
ArrayList
クラスには、TinyMapModule
オブジェクトのモジュールメンバーがありますTinyMapModule
ArrayList
クラスには、TinyMapMacro
オブジェクトのマクロメンバーがありますTinyMapMacro
クラスは、私が厳密に必要とする唯一の属性を持つオブジェクトをマップします。
上記のJSON文字列をオブジェクトに逆シリアル化しようとすると、JSONを逆シリアル化できないことを通知する例外が発生します。
Exception in thread "main" com.fasterxml.jackson.databind.RuntimeJsonMappingException: Can not deserialize instance of it.asystelsrl.hcsbridge.communication.TinyMapModule out of START_ARRAY token
at [Source: java.io.StringReader@3c50507; line: 1, column: 2]
at com.fasterxml.jackson.databind.MappingIterator.next(MappingIterator.java:122)
at it.asystelsrl.hcsbridge.communication.TinyMap.buildTinyMap(TinyMap.java:47)
at it.asystelsrl.hcsbridge.tests.TestTinyMap.main(TestTinyMap.java:69)
Caused by: com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of it.asystelsrl.hcsbridge.communication.TinyMapModule out of START_ARRAY token
at [Source: java.io.StringReader@3c50507; line: 1, column: 2]
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:164)
at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:599)
at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:593)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromArray(BeanDeserializer.java:531)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:141)
at com.fasterxml.jackson.databind.MappingIterator.nextValue(MappingIterator.java:188)
at com.fasterxml.jackson.databind.MappingIterator.next(MappingIterator.java:120)
... 2 more
Jacksonアノテーション、カスタムデシリアライザーなどについてはすでにたくさん読んでいますが、私が思いついた唯一の解決策は、TinyMap.modules
メンバーをからArrayList<TinyMapModules>
に変換しArrayList<Object>
、カスタムデシリアライザーを使用してNullTypeオブジェクトを処理することです。
この選択によって(可能であれば、まだテストしていないため)、TinyMap.modules
メンバーのセマンティック値が失われ、強制されることはありません。
null要素の問題を解決する別の方法はありますか?
編集:
この構造内でnull以外のオブジェクトの順序位置を保持できることが重要なので、少なくともnull要素をプレースホルダーとして使用できるものに置き換える必要があります。