कुछ क्षेत्रों के लिए जैक्सन JSON कस्टम क्रमांकन


93

वहाँ एक रास्ता जैक्सन JSON प्रोसेसर का उपयोग करने के लिए कस्टम क्षेत्र स्तर serialization कर रहा है? उदाहरण के लिए, मुझे कक्षा पसंद है

public class Person {
    public String name;
    public int age;
    public int favoriteNumber;
}

JSON का अनुसरण करने के लिए क्रमबद्ध:

{ "name": "Joe", "age": 25, "favoriteNumber": "123" }

ध्यान दें कि उम्र = 25 एक संख्या के रूप में एन्कोडेड है जबकि पसंदीदाएनआर = 123 एक स्ट्रिंग के रूप में एन्कोडेड है । बॉक्स से बाहर जैक्सन intएक नंबर पर मार्शल्स । इस मामले में मैं चाहता हूं कि पसंदीदानंबर को एक स्ट्रिंग के रूप में एन्कोड किया जाए।


1
मैंने जैक्सन के साथ एक कस्टम सीरियल लिखने वाले के बारे में एक पोस्ट लिखी जो कुछ लोगों के लिए उपयोगी हो सकती है।
सैम बेरी

जवाबों:


106

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

public class Person {
    public String name;
    public int age;
    @JsonSerialize(using = IntToStringSerializer.class, as=String.class)
    public int favoriteNumber:
}


public class IntToStringSerializer extends JsonSerializer<Integer> {

    @Override
    public void serialize(Integer tmpInt, 
                          JsonGenerator jsonGenerator, 
                          SerializerProvider serializerProvider) 
                          throws IOException, JsonProcessingException {
        jsonGenerator.writeObject(tmpInt.toString());
    }
}

जावा से autoboxing संभाल चाहिए intकरने के लिए Integerआप के लिए।


3
जैक्सन-डेटाबाइंड (कम से कम 2.1.3) में पहले से ही विशेष ToStringSerializer शामिल हैं, मेरा उत्तर देखें।
werupokz

@KevinBowersox आप मेरी deserializing समस्या के साथ मदद कर सकते हैं ?
JJD


क्या ऐसा करने का कोई कम भयानक तरीका नहीं है? पसंद है Person implements ToJson?
jameshfisher

1
मेरे मामले में, यह as=String.classमेरे द्वारा उपयोग किए जाने वाले प्रकारों के कारण भी असफल रहा। @ केविन-बोर्सॉक्स, मैं आपकी टिप्पणी को अपडेट करने का सुझाव देता हूं, जो @GarethLatty के अनुरूप है।
बर्ट

54

जैक्सन-डेटाबाइंड (कम से कम 2.1.3) विशेष प्रदान करता है ToStringSerializer( com.fasterxml.jackson.databind.ser.std.ToStringSerializer)

उदाहरण:

public class Person {
    public String name;
    public int age;
    @JsonSerialize(using = ToStringSerializer.class)
    public int favoriteNumber:
}

3
रिवर्स के बारे में क्या जहां स्ट्रिंग को एक इंट में बदलने की आवश्यकता है? मैं ToIntSerializer.class नहीं देखता।
jEremyB

@jEremyB आपको एक कस्टम
ड्रू स्टीफंस

ToStringSerializer काम करता है, लेकिन FloatSerializer यह संदेश लाता है: सामग्री नहीं लिख सका: java.lang.Integer को java.lang.Float में नहीं डाला जा सकता
Arnie Schwarzvogel

11

एक @JsonPropertyएनोटेट गेट्टर जोड़ें , जो क्षेत्र के Stringलिए एक रिटर्न देता है favoriteNumber:

public class Person {
    public String name;
    public int age;
    private int favoriteNumber;

    public Person(String name, int age, int favoriteNumber) {
        this.name = name;
        this.age = age;
        this.favoriteNumber = favoriteNumber;
    }

    @JsonProperty
    public String getFavoriteNumber() {
        return String.valueOf(favoriteNumber);
    }

    public static void main(String... args) throws Exception {
        Person p = new Person("Joe", 25, 123);
        ObjectMapper mapper = new ObjectMapper();
        System.out.println(mapper.writeValueAsString(p)); 
        // {"name":"Joe","age":25,"favoriteNumber":"123"}
    }
}

11

जैकसन-एनोटेशन प्रदान करता है @JsonFormatजो कि कस्टम धारावाहिक लिखने की आवश्यकता के बिना बहुत सारे अनुकूलन को संभाल सकता है।

उदाहरण के लिए, STRINGसंख्यात्मक प्रकार वाले फ़ील्ड के लिए आकार का अनुरोध करना स्ट्रिंग के रूप में संख्यात्मक मान का उत्पादन करेगा

public class Person {
    public String name;
    public int age;
    @JsonFormat(shape = JsonFormat.Shape.STRING)
    public int favoriteNumber;
}

वांछित उत्पादन में परिणाम होगा

{"name":"Joe","age":25,"favoriteNumber":"123"}

7

यदि आप एनोटेशन के साथ अपने मॉडल को प्रदूषित नहीं करना चाहते हैं और कुछ कस्टम ऑपरेशन करना चाहते हैं, तो आप मिक्सी का उपयोग कर सकते हैं।

ObjectMapper mapper = new ObjectMapper();
SimpleModule simpleModule = new SimpleModule();
simpleModule.setMixInAnnotation(Person.class, PersonMixin.class);
mapper.registerModule(simpleModule);

ओवरराइड आयु:

public abstract class PersonMixin {
    @JsonSerialize(using = PersonAgeSerializer.class)
    public String age;
}

उम्र के साथ आपको जो कुछ भी चाहिए वह करें:

public class PersonAgeSerializer extends JsonSerializer<Integer> {
    @Override
    public void serialize(Integer integer, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        jsonGenerator.writeString(String.valueOf(integer * 52) + " months");
    }
}

2

@ जसन व्यू की मदद से हम मॉडल कक्षाओं के क्षेत्र तय कर सकते हैं ताकि यह निर्धारित किया जा सके कि न्यूनतम मानदंड (हमें मानदंडों को परिभाषित करना है) जैसे कि हमारे पास 10 गुणों के साथ एक कोर वर्ग हो सकता है, लेकिन केवल 5 संपत्तियों को क्रमबद्ध किया जा सकता है जो ग्राहक के लिए आवश्यक हैं। केवल

केवल निम्न वर्ग बनाकर हमारे दृश्यों को परिभाषित करें:

public class Views
{
    static class Android{};
    static class IOS{};
    static class Web{};
}

विचारों के साथ एनोटेट मॉडल वर्ग:

public class Demo 
{
    public Demo() 
    {
    }

@JsonView(Views.IOS.class)
private String iosField;

@JsonView(Views.Android.class)
private String androidField;

@JsonView(Views.Web.class)
private String webField;

 // getters/setters
...
..
}

अब हम बस के रूप में वसंत से HttpMessageConverter वर्ग का विस्तार करके कस्टम json कनवर्टर लिखना है:

    public class CustomJacksonConverter implements HttpMessageConverter<Object> 
    {
    public CustomJacksonConverter() 
        {
            super();
        //this.delegate.getObjectMapper().setConfig(this.delegate.getObjectMapper().getSerializationConfig().withView(Views.ClientView.class));
        this.delegate.getObjectMapper().configure(MapperFeature.DEFAULT_VIEW_INCLUSION, true);
        this.delegate.getObjectMapper().setSerializationInclusion(Include.NON_NULL);

    }

    // a real message converter that will respond to methods and do the actual work
    private MappingJackson2HttpMessageConverter delegate = new MappingJackson2HttpMessageConverter();

    @Override
    public boolean canRead(Class<?> clazz, MediaType mediaType) {
        return delegate.canRead(clazz, mediaType);
    }

    @Override
    public boolean canWrite(Class<?> clazz, MediaType mediaType) {
        return delegate.canWrite(clazz, mediaType);
    }

    @Override
    public List<MediaType> getSupportedMediaTypes() {
        return delegate.getSupportedMediaTypes();
    }

    @Override
    public Object read(Class<? extends Object> clazz,
            HttpInputMessage inputMessage) throws IOException,
            HttpMessageNotReadableException {
        return delegate.read(clazz, inputMessage);
    }

    @Override
    public void write(Object obj, MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException 
    {
        synchronized(this) 
        {
            String userAgent = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getHeader("userAgent");
            if ( userAgent != null ) 
            {
                switch (userAgent) 
                {
                case "IOS" :
                    this.delegate.getObjectMapper().setConfig(this.delegate.getObjectMapper().getSerializationConfig().withView(Views.IOS.class));
                    break;
                case "Android" :
                    this.delegate.getObjectMapper().setConfig(this.delegate.getObjectMapper().getSerializationConfig().withView(Views.Android.class));
                    break;
                case "Web" :
                    this.delegate.getObjectMapper().setConfig(this.delegate.getObjectMapper().getSerializationConfig().withView( Views.Web.class));
                    break;
                default:
                    this.delegate.getObjectMapper().setConfig(this.delegate.getObjectMapper().getSerializationConfig().withView( null ));
                    break;
                }
            }
            else
            {
                // reset to default view
                this.delegate.getObjectMapper().setConfig(this.delegate.getObjectMapper().getSerializationConfig().withView( null ));
            }
            delegate.write(obj, contentType, outputMessage);
        }
    }

}

अब इस कस्टम जोंस कन्वर्ट को डिस्पैचर-सर्वलेट.एक्सएमएल में डालकर उपयोग करने के लिए वसंत को बताने की जरूरत है

<mvc:annotation-driven>
        <mvc:message-converters register-defaults="true">
            <bean id="jsonConverter" class="com.mactores.org.CustomJacksonConverter" >
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

कि आप यह तय कर पाएंगे कि किस क्षेत्र को क्रमबद्ध करना है।

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