ジャクソンに次のコンストラクターでクラスをデシリアライズしてほしいです:
_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();
自分で住所を作成するために、ジャクソンからキーと値のペアを取得する方法はありますか?あるいは、ジャクソンにBuilderクラス自体を使用させる方法はありますか?
Jackson 2+を使用している限り、 これをサポートするために構築された があります。
最初に、この注釈をAddress
クラスに追加する必要があります。
@JsonDeserialize(builder = Address.Builder.class)
次に、この注釈をBuilder
クラスに追加する必要があります。
@JsonPOJOBuilder(buildMethodName = "create", withPrefix = "set")
Builderのcreateメソッドの名前をbuildに変更し、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();
}
}
@Rupert Madden-Abbottからの答えは機能します。ただし、デフォルト以外のコンストラクタがある場合、たとえば、
Builder(String city, String country) {...}
次に、以下のようにパラメーターに注釈を付ける必要があります。
@JsonCreator
Builder(@JsonProperty("city") String city,
@JsonProperty("country") String country) {...}
次のように@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();
}
}
この場合に適したソリューション(「Lombok」ビルダーアノテーションを使用しました)。
@Getter
@Builder(builderMethodName = "builder")
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@JsonAutoDetect(
fieldVisibility = JsonAutoDetect.Visibility.ANY,
creatorVisibility = JsonAutoDetect.Visibility.ANY
)
私もあなたの役に立つことを願っています。
ビルダーパターンは現在サポートされていませんが、かなり前にリクエストされています(そして最後にJiraの問題 http://jira.codehaus.org/browse/JACKSON-469 が提出されました)-十分な需要がある場合、1.8リリースで追加される可能性があります(必ずJiraで投票してください!)。これは合理的な追加機能であり、開発者が持っている時間だけ遅延します。しかし、私はそれが素晴らしい追加になると思います。