Jackson を使用してオブジェクトに生の JSON を含めるにはどうすればよいでしょうか? 質問する

Jackson を使用してオブジェクトに生の JSON を含めるにはどうすればよいでしょうか? 質問する

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

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: [ソース: java.io.StringReader@d70d7a; 行: 1、列: 13] の START_OBJECT トークンから java.lang.String のインスタンスをデシリアライズできません (参照チェーン経由: com.tnal.prism.cobalt.gather.testing.Pojo["bar"])

Jackson はなぜ一方向では問題なく機能するのに、逆方向になると失敗するのでしょうか。自身の出力を再び入力として受け取ることができるはずです。私がしようとしていることは非正統的であることはわかっています (一般的なアドバイスは、barという名前のプロパティを持つ の内部オブジェクトを作成することですA) が、この JSON とはまったくやり取りしたくありません。私のコードはこのコードのパススルーとして機能しています。この JSON を受け取って、何も変更せずに再度送信したいのです。JSON が変更されたときにコードを変更する必要がないようにするためです。

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

編集: Pojo を静的クラスにしたため、別のエラーが発生しました。

ベストアンサー1

@JsonRawValue はシリアル化側のみを対象としており、逆方向の処理は少し複雑です。実際には、事前にエンコードされたコンテンツを挿入できるようにするために追加されました。

逆のサポートを追加することは可能だと思いますが、それはかなり厄介です。コンテンツを解析し、その後「生の」形式に書き直す必要がありますが、同じになる場合もあれば、そうでない場合もあります (文字の引用が異なる場合があるため)。これは一般的なケースです。ただし、一部の問題には意味があるかもしれません。

しかし、あなたの特定のケースの回避策は、タイプを 'java.lang.Object' として指定することだと思います。これは問題なく動作するはずです。シリアル化の場合、String はそのまま出力され、デシリアライズの場合、Map としてデシリアライズされます。実際には、その場合は別の getter/setter が必要になる場合があります。getter はシリアル化のために String を返し (@JsonRawValue が必要)、setter は Map または Object のいずれかを受け取ります。それが理にかなっている場合は、String に再エンコードできます。

おすすめ記事