सीरियलाइज़ेशन और डिसिएरलाइज़ेशन के दौरान JSON संपत्ति के विभिन्न नाम


149

क्या यह संभव है: कक्षा में एक क्षेत्र है, लेकिन जैक्सन पुस्तकालय में क्रमांकन / विचलन के दौरान इसके लिए अलग-अलग नाम हैं?

उदाहरण के लिए, मेरे पास "कोऑर्डिएंट्स" वर्ग है।

class Coordinates{
  int red;
}

JSON से deserialization के लिए इस तरह प्रारूप करना चाहते हैं:

{
  "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.UrerecognizedPropertyException: गैर-मान्यताप्राप्त फ़ील्ड "लाल"

जवाबों:


203

बस परीक्षण किया गया है और यह काम करता है:

public class Coordinates {
    byte red;

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

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

विचार यह है कि विधि के नाम अलग-अलग होने चाहिए, इसलिए जैकसन इसे विभिन्न क्षेत्रों के रूप में बताता है, एक क्षेत्र के रूप में नहीं।

यहाँ परीक्षण कोड है:

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

क्या jaxb के साथ भी ऐसा ही संभव है?
कुई पेंगफेई

38

आप उपयोग कर सकते हैं @jsonAliasजो जैकसन 2.9.0 में पेश किया गया है

उदाहरण:

public class Info {
  @JsonAlias({ "red" })
  public String r;
}

यह rक्रमांकन के दौरान उपयोग करता है , लेकिन reddeserialization के दौरान एक उपनाम के रूप में अनुमति देता है । यह अभी भी rdeserialized के रूप में अच्छी तरह से करने की अनुमति देता है।


8
@JsonAlias के लिए दस्तावेज़ स्पष्ट रूप से यह है कि कहा गया है has no effect during serialization where primary name is always used। यह वह नहीं है जो ओपी चाहता है।
Xaero Degreaz

3
@XaeroDegreaz मुझे लगता है कि @Asura का मतलब है, कि आप rप्राथमिक नाम के रूप में उपयोग कर सकते हैं , लेकिन इसके redलिए @JsonAlias, जो इसे क्रमबद्ध करने की अनुमति देता है r, लेकिन reddeserialization पर पहचाना जाता है। इसके साथ एनोटेट करना @JsonProperty("r")और इसके अलावा @JsonAlias("red")दी गई समस्या के लिए ठीक काम करना चाहिए।
जेरोट

16

आप अपनी संपत्ति के क्रमिकरण , और क्रमांकन को नियंत्रित करने के लिए क्रमशः @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;
    }
}

15

मैं दो अलग-अलग गेटर्स / बाइंडर्स पेयर को एक वेरिएबल में बाँधूँगा:

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

13
लेकिन इस मामले में, क्रमांकन के दौरान, हमें दोनों गुण मिलेंगे: "आर" और "लाल", समान मूल्यों के साथ।
kiRach

@JsonIgnore उन विधियों पर जिन्हें आप संसाधित नहीं करना चाहते हैं, उस समस्या को ठीक कर देंगे
Stephan

आजकल अधिक सुविधाजनक एनोटेशन हैं: @JsonGetterऔर @JsonSetter। तो कोई ठीक से सेट कर सकता है कि धारावाहिक कैसे व्यवहार करेगा।
DRCB

6

सामान्य गेट्टर / सेटर पेयर होना संभव है। आपको बस एक्सेस मोड निर्दिष्ट करना होगा@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"}

5

यह वह नहीं था जो मैं एक समाधान के रूप में उम्मीद कर रहा था (हालांकि यह एक वैध उपयोग मामला है)। मेरी आवश्यकता एक मौजूदा छोटी गाड़ी ग्राहक (एक मोबाइल ऐप जो पहले से जारी है) को वैकल्पिक नामों का उपयोग करने की अनुमति थी।

समाधान इस तरह एक अलग सेटर विधि प्रदान करने में निहित है:

@JsonSetter( "r" )
public void alternateSetRed( byte red ) {
    this.red = red;
}

2

मुझे इसका एक पुराना सवाल पता है, लेकिन मेरे लिए यह काम कर रहा है जब मुझे पता चला कि इसका विरोधाभासी ज्ञान पुस्तकालय के साथ है इसलिए यदि आप Gson का उपयोग कर रहे हैं तो आशा के @SerializedName("name")बजाय उपयोग @JsonProperty("name")करें इससे मदद मिलती है


2

साथ टिप्पणी करना @JsonAliasजो उल्लेख किए बिना, जैक्सन 2.9+ के साथ पेश किया गया @JsonPropertyमद पर एक से अधिक अन्य नाम (एक json संपत्ति के लिए अलग-अलग नाम) ठीक काम करता है के साथ deserialized किया जाना है।

मैंने अपने उपयोग-मामले के com.fasterxml.jackson.annotation.JsonAliasलिए पैकेज की संगति का com.fasterxml.jackson.databind.ObjectMapperउपयोग किया।

उदाहरण के लिए:

@Data
@Builder
public class Chair {

    @JsonAlias({"woodenChair", "steelChair"})
    private String entityType;

}


@Test
public void test1() {

   String str1 = "{\"woodenChair\":\"chair made of wood\"}";
   System.out.println( mapper.readValue(str1, Chair.class));
   String str2 = "{\"steelChair\":\"chair made of steel\"}";
   System.out.println( mapper.readValue(str2, Chair.class));

}

बस ठीक काम करता है।


1

उन्होंने इसे एक विशेषता के रूप में शामिल किया होगा, क्योंकि अब @JsonPropertyएक गेटटर और सेटर के परिणाम के लिए अलग सेट करने से आपको वही उम्मीद होगी (जो कि समान क्षेत्र के लिए क्रमिकरण और डीरियलाइज़ेशन के दौरान अलग-अलग संपत्ति का नाम है)। जैक्सन संस्करण 2.6.7


0

आप ऐसा करने के लिए एक क्रमबद्ध वर्ग लिख सकते हैं:

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);
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.