1

編集:あなたの何人かの要求により、私は私の実際のデータ構造とクラスを投稿しています。私はあなたが問題を理解しやすくすることに失敗しました。

nullJackson 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");
} 
... 

極端な統合では、問題を次のように図式化しようとしました。

  1. TinyMapArrayListクラスには、TinyMapModuleオブジェクトのモジュールメンバーがあります
  2. TinyMapModuleArrayListクラスには、TinyMapMacroオブジェクトのマクロメンバーがあります
  3. 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要素をプレースホルダーとして使用できるものに置き換える必要があります。

4

2 に答える 2

2

ここでの問題は、私がジャクソンを使って多くの混乱を引き起こしたことです。

ProgrammerBruceによるこの記事を読んで理解するようになりました。

StaxManが彼のコメントで示唆したように、私はコレクションをそうでないものに逆シリアル化しようとしていました。

有用で明確な記事を提供してくれたProgrammerBruceに感謝します。

于 2012-11-02T10:30:27.190 に答える
1

完全なオブジェクトtheBeansではなく、サンプルJSONのプロパティのみを表示しています。MyContainerそして、あなたのエラーは、それが実際に与えられたJSONをとして解析しようとしているように聞こえますMyContainer

念のために言っておきますが、完全なJSONオブジェクトと逆シリアル化コードを投稿できますか?

JacksonはnullPOJOをうまく理解しています。

于 2012-10-31T19:27:52.083 に答える