Différents noms de propriétés JSON lors de la sérialisation et de la desérialisation

est-il possible: d'avoir un champ dans la classe, mais des noms différents pour lui lors de la sérialisation/deserialisation dans la bibliothèque Jackson?

par exemple, j'ai la classe"Coordiantes".

class Coordinates{
  int red;
}

pour la desérialisation de JSON veulent avoir le format suivant:

{
  "red":12
}

mais quand je vais sérialiser l'objet, le résultat devrait être comme celui-ci:

{
  "r":12
}

j'ai essayé de mettre en œuvre ce par appliquer @JsonProperty annotation à la fois sur getter et setter (avec des valeurs différentes):

class Coordiantes{
    int red;

    @JsonProperty("r")
    public byte getRed() {
      return red;
    }

    @JsonProperty("red")
    public void setRed(byte red) {
      this.red = red;
    }
}

mais j'ai eu une exception:

org.codehaus.Jackson.cartographie.exc.Nonrecognizedpropertyexception: Non recognized field " red

114
demandé sur Paul Rooney 2011-12-19 15:01:49

8 réponses

vient d'être testé et cela fonctionne:

public class Coordinates {
    byte red;

    @JsonProperty("r")
    public byte getR() {
      return red;
    }

    @JsonProperty("red")
    public void setRed(byte red) {
      this.red = red;
    }
}

l'idée est que les noms de méthode devraient être différents, donc jackson Les analyse comme des champs différents, pas comme un seul champ.

voici le code d'essai:

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());

résultat:

Serialization: {"r":5}
Deserialization: 25
156
répondu bezmax 2011-12-19 11:26:51

vous pouvez utiliser @jsonAlias qui a été introduit dans jackson 2.9.0

exemple:

public class Info {
  @JsonAlias({ "r", "red" })
  public String r;
}
15
répondu Asura 2017-08-09 16:40:37

Je lierais deux paires getters/setters différentes à une variable:

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;
    }
}
15
répondu DRCB 2018-03-02 21:27:53

vous pouvez utiliser une combinaison de @JsonSetter , et @jsongetter pour contrôler la desérialisation, et la sérialisation de votre propriété, respectivement.

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;
    }
}
8
répondu Xaero Degreaz 2018-02-27 17:45:08

ce n'était pas ce que j'attendais comme solution (bien qu'il s'agisse d'un cas d'usage légitime). Mon exigence était de permettre à un client buggy existant (une application mobile déjà disponible) d'utiliser d'autres noms.

la solution consiste à fournir une méthode de setter séparée comme celle-ci:

@JsonSetter( "r" )
public void alternateSetRed( byte red ) {
    this.red = red;
}
4
répondu Andy Talkowski 2015-05-20 22:27:04

il est possible d'avoir une paire normale getter/setter. Vous avez juste besoin de spécifier le mode d'accès dans @JsonProperty

voici un test unitaire pour cela:

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);
  }
}

j'ai obtenu la sortie comme suit:

Serialized colotObject: {"device_color":"red"}
4
répondu Raman Yelianevich 2017-02-01 11:46:16

ils ont dû inclure ceci comme une fonctionnalité, parce que maintenant la définition d'un @JsonProperty différent pour un getter et un setter résulte exactement ce que vous attendez (nom de propriété différent pendant la sérialisation et la deserialisation pour le même champ). Jackson version 2.6.7

1
répondu fetta 2016-07-16 10:54:18

vous pouvez écrire une classe de serialize pour faire cela:

symbole de classe publique

{ symbole de corde privée;

 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 {

@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);
0
répondu Vernon Kujyio 2015-11-18 06:02:30