ジャクソン+ビルダーパターン?


89

Jacksonに次のコンストラクターを使用してクラスを逆シリアル化してもらいたいです。

public Clinic(String name, Address address)

最初の引数の逆シリアル化は簡単です。問題は、アドレスが次のように定義されていることです。

public class Address {
  private Address(Map<LocationType, String> components)
  ...

  public static class Builder {
    public Builder setCity(String value);
    public Builder setCountry(String value);
    public Address create();
  }
}

次のように構成されています。 new Address.Builder().setCity("foo").setCountry("bar").create();

自分でアドレスを作成するために、ジャクソンからキーと値のペアを取得する方法はありますか?あるいは、JacksonにBuilderクラス自体を使用させる方法はありますか?

回答:


139

Jackson 2+を使用している限り、これに対するサポートが組み込まれています。

まず、このアノテーションをAddressクラスに追加する必要があります。

@JsonDeserialize(builder = Address.Builder.class)

次に、このアノテーションをBuilderクラスに追加する必要があります。

@JsonPOJOBuilder(buildMethodName = "create", withPrefix = "set")

Builderのcreateメソッドの名前をビルドに変更し、Builderのセッターにsetではなく接頭辞を付ける場合は、この2番目のアノテーションをスキップできます。

完全な例:

@JsonDeserialize(builder = Address.Builder.class)
public class Address
{
  private Address(Map<LocationType, String> components)
  ...

  @JsonPOJOBuilder(buildMethodName = "create", withPrefix = "set")
  public static class Builder
  {
    public Builder setCity(String value);
    public Builder setCountry(String value);
    public Address create();
  }
}

14
@JsonPOJOBuilderアノテーションをまとめて削除したい場合は、「create」の名前を「build」に変更し、各ビルダーセッターに@JsonProperty。でアノテーションを付けます。
サム・ベリー

これは金色です。ありがとう。
Mukul Goel 2017

これは現在時代遅れであり、Lombok 1.18.4を使用する@Jacksonizedと、内部ビルダーとジャクソンアノテーションが1つに置き換えられます
Randakar

@Randakar a)@Jackonized はロンボクでリリースされたばかりの実験的な機能であるため、これは時代遅れではないと思います 。実験的な機能の採用を不必要に奨励するのは良い考えではないと思います。b)質問がロンボクについて言及または使用していない。問題を解決するために不必要に依存関係を導入するのは良い考えではないと思います。
ルパートマッデン-アボット

19

@ RupertMadden-Abbottからの回答は機能します。ただし、デフォルト以外のコンストラクターがある場合、たとえば、

Builder(String city, String country) {...}

次に、以下のようにパラメーターに注釈を付ける必要があります。

@JsonCreator
Builder(@JsonProperty("city")    String city, 
        @JsonProperty("country") String country) {...}

9

この場合、私に適したソリューションです(「Lombok」ビルダーアノテーションを使用しました)。

@Getter
@Builder(builderMethodName = "builder")
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@JsonAutoDetect(
    fieldVisibility = JsonAutoDetect.Visibility.ANY,
    creatorVisibility = JsonAutoDetect.Visibility.ANY
)

私もあなたに役立つことを願っています。


これは現在時代遅れであり、Lombok 1.18.4を使用する@Jacksonizedと、内部ビルダーとジャクソンアノテーションを1つに置き換えることができます
Randakar

7

私は次のように@JsonDeserializeを使用してこれを実装することになりました:

@JsonDeserialize(using = JacksonDeserializer.class)
public class Address
{...}

@JsonCachable
static class JacksonDeserializer extends JsonDeserializer<Address>
{
    @Override
    public Address deserialize(JsonParser parser, DeserializationContext context)
        throws IOException, JsonProcessingException
    {
        JsonToken token = parser.getCurrentToken();
        if (token != JsonToken.START_OBJECT)
        {
            throw new JsonMappingException("Expected START_OBJECT: " + token, parser.getCurrentLocation());
        }
        token = parser.nextToken();
        Builder result = new Builder();
        while (token != JsonToken.END_OBJECT)
        {
            if (token != JsonToken.FIELD_NAME)
            {
                throw new JsonMappingException("Expected FIELD_NAME: " + token, parser.getCurrentLocation());
            }
            LocationType key = LocationType.valueOf(parser.getText());

            token = parser.nextToken();
            if (token != JsonToken.VALUE_STRING)
            {
                throw new JsonMappingException("Expected VALUE_STRING: " + token, parser.getCurrentLocation());
            }
            String value = parser.getText();

            // Our Builder allows passing key-value pairs
            // alongside the normal setter methods.
            result.put(key, value);
            token = parser.nextToken();
        }
        return result.create();
    }
}

これはあなたがそれを実装することになった方法かもしれませんが、この答えは実際に提起された質問に答えません。@Rupert Madden-Abbottによって投稿された回答は、承認済みとしてマークする必要があります。
kelnos

2

かなり前にリクエストされましたが(そして最終的にJiraの問題http://jira.codehaus.org/browse/JACKSON-469が提出されました)、現在ビルダーパターンのサポートはありません-これは追加される可能性があります十分な需要がある場合は1.8リリースの場合(Jiraで投票してください!)。これは合理的な追加機能であり、開発者が持っている時間だけ遅れます。しかし、それは素晴らしい追加になると思います。


2
CodehausではJiraを利用できなくなりましたが、リンクされた問題については、wiki.fasterxml.com
Paul

ビルダーパターンのサポートは、Jackson 2.2のように、長い間追加されてきました。
StaxMan 2016年

2

これは私にとってはうまくいきました:@NoArgsConstructorこれの唯一の欠点は、= new ADTO()を再び実行できることです。しかし、ねえ、私はとにかくコード警察が好きではなく、誰かのコードの使い方を教えてくれます:-)だから、私のPOJODTOSを好きなように使ってください。ビルダーの有無にかかわらず。私は提案します:ビルダーでそれをします、しかし私のゲストになってください...

@Data
@Builder
//Dont forget this! Otherwise no Jackson serialisation possible!
@NoArgsConstructor
@AllArgsConstructor
public class ADTO {
.....
}

あなたは誰かのコードの使い方を知りたくないですか?
masterxilo
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.