可能です:クラスに1つのフィールドを持ち、ジャクソンライブラリでのシリアル化/逆シリアル化中に異なる名前を付けることはできますか?
たとえば、クラス「Coordiantes」があります。
class Coordinates{
int red;
}
JSONからの逆シリアル化では、次のような形式が必要です。
{
"red":12
}
しかし、オブジェクトをシリアル化すると、結果は次のようになります。
{
"r":12
}
私はゲッターとセッターの両方に(異なる値で)@JsonProperty
注釈を適用することでこれを実装しようとしました:
class Coordiantes{
int red;
@JsonProperty("r")
public byte getRed() {
return red;
}
@JsonProperty("red")
public void setRed(byte red) {
this.red = red;
}
}
しかし、私は例外を得ました:
org.codehaus.jackson.map.exc.UnrecognizedPropertyException:認識されないフィールド「赤」
テストしたところ、これは機能します。
public class Coordinates {
byte red;
@JsonProperty("r")
public byte getR() {
return red;
}
@JsonProperty("red")
public void setRed(byte red) {
this.red = red;
}
}
メソッド名は異なる必要があるため、jacksonはそれを1つのフィールドとしてではなく、異なるフィールドとして解析します。
テストコードは次のとおりです。
Coordinates c = new Coordinates();
c.setRed((byte) 5);
ObjectMapper mapper = new ObjectMapper();
System.out.println("Serialization: " + mapper.writeValueAsString(c));
Coordinates r = mapper.readValue("{\"red\":25}",Coordinates.class);
System.out.println("Deserialization: " + r.getR());
結果:
Serialization: {"r":5}
Deserialization: 25
Jackson 2.9.0で導入された@jsonAliasを使用できます。
例:
public class Info {
@JsonAlias({ "r", "red" })
public String r;
}
2つの異なるゲッター/セッターのペアを1つの変数にバインドします。
class Coordinates{
int red;
@JsonProperty("red")
public byte getRed() {
return red;
}
public void setRed(byte red) {
this.red = red;
}
@JsonProperty("r")
public byte getR() {
return red;
}
public void setR(byte red) {
this.red = red;
}
}
@ JsonSetter と @ JsonGetter の組み合わせを使用して、プロパティの逆シリアル化とシリアル化をそれぞれ制御できます。
import com.fasterxml.jackson.annotation.JsonSetter;
import com.fasterxml.jackson.annotation.JsonGetter;
class Coordinates {
private int red;
//# Used during serialization
@JsonGetter("r")
public int getRed() {
return red;
}
//# Used during deserialization
@JsonSetter("red")
public void setRed(int red) {
this.red = red;
}
}
これは、私が解決策として期待していたものではありませんでした(正当なユースケースですが)。私の要件は、既存のバグのあるクライアント(既にリリースされたモバイルアプリ)が別名を使用できるようにすることでした。
解決策は、次のような個別のセッターメソッドを提供することです。
@JsonSetter( "r" )
public void alternateSetRed( byte red ) {
this.red = red;
}
通常のゲッター/セッターのペアを持つことは可能です。 @JsonProperty
でアクセスモードを指定するだけです。
そのための単体テストは次のとおりです。
public class JsonPropertyTest {
private static class TestJackson {
private String color;
@JsonProperty(value = "device_color", access = JsonProperty.Access.READ_ONLY)
public String getColor() {
return color;
};
@JsonProperty(value = "color", access = JsonProperty.Access.WRITE_ONLY)
public void setColor(String color) {
this.color = color;
}
}
@Test
public void shouldParseWithAccessModeSpecified() throws Exception {
String colorJson = "{\"color\":\"red\"}";
ObjectMapper mapper = new ObjectMapper();
TestJackson colotObject = mapper.readValue(colorJson, TestJackson.class);
String ser = mapper.writeValueAsString(colotObject);
System.out.println("Serialized colotObject: " + ser);
}
}
出力は次のようになりました。
Serialized colotObject: {"device_color":"red"}
ゲッターとセッターに異なる@JsonProperty
を設定すると、期待どおりの結果になります(同じフィールドのシリアライズとデシリアライズ中に異なるプロパティ名が使用されるため)。 Jacksonバージョン2.6.7
私はその古い質問を知っていますが、私はGsonライブラリと競合していることがわかったので動作しましたので、Gsonを使用している場合は@SerializedName("name")
の代わりに@JsonProperty("name")
を使用してください
あなたはそれを行うためにシリアル化クラスを書くことができます:
public class Symbol
{
private String symbol;
private String name;
public String getSymbol() {
return symbol;
}
public void setSymbol(String symbol) {
this.symbol = symbol;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class SymbolJsonSerializer extends JsonSerializer<Symbol> {
@Override
public void serialize(Symbol symbol, JsonGenerator jgen, SerializerProvider serializers) throws IOException, JsonProcessingException {
jgen.writeStartObject();
jgen.writeStringField("symbol", symbol.getSymbol());
//Changed name to full_name as the field name of Json string
jgen.writeStringField("full_name", symbol.getName());
jgen.writeEndObject();
}
}
ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addSerializer(Symbol.class, new SymbolJsonSerializer());
mapper.registerModule(module);
//only convert non-null field, option...
mapper.setSerializationInclusion(Include.NON_NULL);
String jsonString = mapper.writeValueAsString(symbolList);