1. ホーム
  2. java

[解決済み] Jacksonを使用して、生のJSONをオブジェクトに含めるにはどうすればよいですか?

2022-05-13 19:37:37

質問

私は、オブジェクトが Jackson を使用して (de) シリアル化されるときに、生の JSON を Java オブジェクトの内部に含めようとしています。この機能をテストするために、次のようなテストを書きました。

public static class Pojo {
    public String foo;

    @JsonRawValue
    public String bar;
}

@Test
public void test() throws JsonGenerationException, JsonMappingException, IOException {

    String foo = "one";
    String bar = "{\"A\":false}";

    Pojo pojo = new Pojo();
    pojo.foo = foo;
    pojo.bar = bar;

    String json = "{\"foo\":\"" + foo + "\",\"bar\":" + bar + "}";

    ObjectMapper objectMapper = new ObjectMapper();
    String output = objectMapper.writeValueAsString(pojo);
    System.out.println(output);
    assertEquals(json, output);

    Pojo deserialized = objectMapper.readValue(output, Pojo.class);
    assertEquals(foo, deserialized.foo);
    assertEquals(bar, deserialized.bar);
}

このコードは、次のような行を出力します。

{"foo":"one","bar":{"A":false}}

JSONはまさに私が望むような形です。残念ながら、このコードはJSONをオブジェクトに読み込もうとすると例外が発生して失敗します。以下はその例外です。

org.codehaus.jackson.map.JsonMappingException: START_OBJECTトークンからjava.lang.Stringのインスタンスをデシリアライズできません。 at [Source: java.io.StringReader@d70d7a; line: 1, column: 13] (through reference chain: com.tnal.prism.cobalt.gather.testing.Pojo["bar"])

Jackson は、一方向にはうまく機能するのに、もう一方に進むと失敗するのはなぜですか? それは、それ自身の出力を再び入力として受け取ることができるはずのように思われます。私がやろうとしていることが正統派でないことは分かっています (一般的なアドバイスでは、インナー オブジェクトを bar という名前のプロパティを持つ A という名前のプロパティを持つ)、しかし私はこのJSONと全く対話したくありません。私のコードはこのコードのパススルーとして動作しています。この JSON を取り込み、何も触らずに再び送り返したいのです。

アドバイスありがとうございます。

EDIT: Pojoを静的クラスにしたところ、別のエラーが発生しました。

どのように解決するのですか?

JsonRawValueはシリアライズ側のみを対象としており、逆方向は少し扱いにくいからです。事実上、それは事前にエンコードされたコンテンツを注入することを可能にするために追加されました。

コンテンツは解析され、quot;raw" 形式に書き戻されなければなりませんが、同じであるかどうかはわかりません (文字の引用が異なる場合があるため)。 これは一般的な場合です。しかし、おそらくそれは問題のいくつかのサブセットに対して意味をなすでしょう。

しかし、私はあなたの特定のケースのためのワークアラウンドは、'java.lang.Object'として型を指定することであると思います。ゲッターはシリアライズのためにStringを返し(そして@JsonRawValueが必要)、セッターはMapかObjectのどちらかを取る。もしそれが理にかなっているならば、それをStringに再エンコードすることもできます。