স্প্রিং বুট দ্বারা স্পষ্টভাবে ব্যবহৃত জ্যাকসন জেএসন ম্যাপার কীভাবে কাস্টমাইজ করবেন?


102

আমি স্প্রিং বুট (১.২.১) ব্যবহার করছি, তাদের বিল্ডিংয়ের মতো একটি রেস্টস্টুল ওয়েব সার্ভিস টিউটোরিয়াল:

@RestController
public class EventController {

    @RequestMapping("/events/all")
    EventList events() {
        return proxyService.getAllEvents();
    }

}

সুতরাং উপরের দিকে, স্প্রিং এমভিসি জ্যাকসনকে স্পষ্টভাবে জেসসনকে আমার EventListবস্তুটি জেএসএন-তে সিরিয়ালের জন্য ব্যবহার করে ।

তবে আমি JSON ফর্ম্যাটে কিছু সাধারণ কাস্টমাইজেশন করতে চাই, যেমন:

setSerializationInclusion(JsonInclude.Include.NON_NULL)

প্রশ্নটি হল, অন্তর্নিহিত জেএসওএন ম্যাপারকে কাস্টমাইজ করার সহজ উপায় কী?

আমি এই ব্লগ পোস্টে পদ্ধতির চেষ্টা করে একটি কাস্টমবজেক্টম্যাপার তৈরি করেছিলাম এবং আরও অনেক কিছু তৈরি করেছিলাম, তবে ধাপ 3, "বসন্তের প্রসঙ্গে ক্লাসগুলি নিবন্ধ করুন" ব্যর্থ হয়েছে:

org.springframework.beans.factory.BeanCreationException: 
  Error creating bean with name 'jacksonFix': Injection of autowired dependencies failed; 
  nested exception is org.springframework.beans.factory.BeanCreationException: 
  Could not autowire method: public void com.acme.project.JacksonFix.setAnnotationMethodHandlerAdapter(org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter); 
  nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: 
  No qualifying bean of type [org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter]   
  found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}

দেখে মনে হচ্ছে যে এই নির্দেশাবলী স্প্রিং এমভিসির পুরানো সংস্করণগুলির জন্য, যখন আমি সাম্প্রতিক স্প্রিং বুটের সাহায্যে এটি কাজ করার সহজ উপায় খুঁজছি।


আপনার কি এই টিকাটি sertedোকানো হয়েছে ?: @ সাপ্রেস ওয়ার্নিংস (Spring "স্প্রিংজভাআউটওরিয়িং ইনস্পেকশন"})
sven.kwiotek

লক্ষ্য করুন যে আপনি যদি স্প্রিং ওয়েবটিও ব্যবহার করেন তবে আপনাকে এই অবজেক্টম্যাপারটি ব্যবহার করার জন্য ম্যানুয়ালি তা জানাতে হবে অন্যথায় এটি এটি নিজস্ব উদাহরণ তৈরি করবে যা কনফিগার করা হবে না। দেখুন stackoverflow.com/questions/7854030/...
Constantino Cronemberger

উত্তর:


117

আপনি যদি স্প্রিং বুট ১.৩ ব্যবহার করে থাকেন তবে আপনি এর মাধ্যমে সিরিয়ালাইজেশন অন্তর্ভুক্তিটি কনফিগার করতে পারেন application.properties:

spring.jackson.serialization-inclusion=non_null

জ্যাকসন ২.7-র পরিবর্তনের পরে, স্প্রিং বুট ১.৪ এর spring.jackson.default-property-inclusionপরিবর্তে নামের একটি সম্পত্তি ব্যবহার করে:

spring.jackson.default-property-inclusion=non_null

"দেখতে জ্যাকসন ObjectMapper কাস্টমাইজ করুন স্প্রিং বুট ডকুমেন্টেশন অধ্যায়"।

আপনি যদি স্প্রিং বুটের পূর্ববর্তী সংস্করণ ব্যবহার করেন তবে স্প্রিং বুটে সিরিয়ালাইজেশন অন্তর্ভুক্তি কনফিগার করার সহজতম উপায় হ'ল আপনার নিজের, যথাযথভাবে কনফিগার করা Jackson2ObjectMapperBuilderশিমের ঘোষণা declare উদাহরণ স্বরূপ:

@Bean
public Jackson2ObjectMapperBuilder objectMapperBuilder() {
    Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
    builder.serializationInclusion(JsonInclude.Include.NON_NULL);
    return builder;
}

4
ঠিক আছে, এটি কাজ করে বলে মনে হচ্ছে। আপনি কোথায় এমন একটি পদ্ধতি রাখবেন? সম্ভবত একটি প্রধান অ্যাপ্লিকেশন শ্রেণিতে (সহ @ComponentScan, @EnableAutoConfigurationইত্যাদি)?
জোনিক

4
হ্যাঁ. এই পদ্ধতিটি @Configurationআপনার অ্যাপের যে কোনও শ্রেণিতে যেতে পারে । মূল Applicationশ্রেণি এটির জন্য একটি ভাল জায়গা।
অ্যান্ডি উইলকিনসন

4
গুরুত্বপূর্ণ দ্রষ্টব্য: জ্যাকসন 2 ওজেক্টম্যাপারবিল্ডার ক্লাসটি বসন্ত-ওয়েব উপাদানটির অংশ এবং সংস্করণ 4.1.1 এ যুক্ত হয়েছিল।
গাওগাং

4
@ নিখরচায় সেটরিশালাইজেশন অন্তর্ভুক্তি
দিমিত্রি কোপরিওয়া

6
থামানো হয়েছে: ObjectMapper.setSerializationInclusion জ্যাকসন 2.7 ... ব্যবহারের এ অসমর্থিত হয়েছে stackoverflow.com/a/44137972/6785908 = non_null পরিবর্তে spring.jackson.default-সম্পত্তি-অন্তর্ভুক্তি
এত র্যান্ডম-শহরবাসী

24

আমি এই প্রশ্নের কিছুটা দেরি করে উত্তর দিচ্ছি, তবে ভবিষ্যতে কেউ হয়ত এটি দরকারী বলে মনে করছেন। নীচের পদ্ধতিটি, প্রচুর অন্যান্য পদ্ধতির পাশাপাশি সর্বোত্তমভাবে কাজ করে এবং আমি ব্যক্তিগতভাবে মনে করি যে কোনও ওয়েব অ্যাপ্লিকেশনকে আরও ভাল মানায়।

@Configuration
@EnableWebMvc
public class WebConfiguration extends WebMvcConfigurerAdapter {

 ... other configurations

@Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
        builder.serializationInclusion(JsonInclude.Include.NON_NULL);
        builder.propertyNamingStrategy(PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES);
        builder.serializationInclusion(Include.NON_EMPTY);
        builder.indentOutput(true).dateFormat(new SimpleDateFormat("yyyy-MM-dd"));
        converters.add(new MappingJackson2HttpMessageConverter(builder.build()));
        converters.add(new MappingJackson2XmlHttpMessageConverter(builder.createXmlMapper(true).build()));
    }
}

4
সাম্প্রতিক সংস্করণে আপনাকে অবশ্যই প্রয়োগ করতে হবেWebMvcConfigurer
জোও পেড্রো স্মিট

হ্যাঁ, লোকেরা, এই সমাধানটি চেষ্টা করুন, আমি অবজেক্টম্যাপারের জন্য শিম সরবরাহ করার চেষ্টা করেছি, তারপরে জ্যাকসন 2 অবজেক্টম্যাপারবিল্ডারের জন্য বিনটি কার্যকর হয়নি এবং কেন এখনও তা আমার কোনও ধারণা নেই। প্রচ্ছদ সংযোজন কাজ!
সোমাল সোমালস্কি

22

অ্যাপ্লিকেশন প্রোপার্টিগুলিতে অনেক কিছুই কনফিগার করা যায়। দুর্ভাগ্যক্রমে এই বৈশিষ্ট্যটি কেবল সংস্করণ 1.3 এ রয়েছে তবে আপনি একটি কনফিগার-ক্লাসে যুক্ত করতে পারেন

@Autowired(required = true)
public void configureJackson(ObjectMapper jackson2ObjectMapper) {
    jackson2ObjectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
}

[আপডেট: আপনাকে অবশ্যই অবজেক্টম্যাপারে কাজ করতে হবে কারণ build()কনফিগারেশনটি চালুর আগে-অর্থসূচককে ডাকা হয়]]


সেটাই ছিল আমার দিনকে বাঁচানোর সমাধান। কনফিগারেশন ক্লাসের পরিবর্তে আমি নিজেই আরআরএসটি নিয়ামকের সাথে এই পদ্ধতিটি যুক্ত না করি।
নেস্টর মিলিয়াভ

21

ডকুমেন্টেশন এটি করার বিভিন্ন উপায় জানিয়েছে।

আপনি যদি ডিফল্টটিকে ObjectMapperপুরোপুরি প্রতিস্থাপন করতে চান তবে @Beanসেই ধরণের একটি নির্ধারণ করুন এবং এটি হিসাবে চিহ্নিত করুন @Primary

কোনও @Beanধরণের সংজ্ঞা Jackson2ObjectMapperBuilderদেওয়া আপনাকে ডিফল্ট ObjectMapperএবং XmlMapper( যথাক্রমে MappingJackson2HttpMessageConverterএবং MappingJackson2XmlHttpMessageConverterযথাক্রমে ব্যবহৃত ) উভয়কেই কাস্টমাইজ করতে দেয় ।


4
ডিফল্ট প্রতিস্থাপন না করে কীভাবে এটি করা যায় ObjectMapper? আমি ডিফল্ট পাশাপাশি একটি কাস্টম রাখা মানে।
soufrk

13

আপনি নিজের বুটস্ট্র্যাপ শ্রেণীর ভিতরে একটি নীচের পদ্ধতি যুক্ত করতে পারেন যা এর সাথে টিকা দেওয়া আছে @SpringBootApplication

    @Bean
    @Primary
    public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
    ObjectMapper objectMapper = builder.createXmlMapper(false).build();
    objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
    objectMapper.configure(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS, false);

    objectMapper.registerModule(new JodaModule());

    return objectMapper;
}

এটি আমার জন্য বুট ২.১.৩ ব্যবহার করে কাজ করেছিল। বসন্ত.জ্যাকসন বৈশিষ্ট্যের কোনও প্রভাব ছিল না।
রিচটোপিয়া

9

spring.jackson.serialization-inclusion=non_null আমাদের জন্য কাজ করতেন

তবে যখন আমরা স্প্রিং বুট সংস্করণটি 1.4.2.RELEASE বা উচ্চতরতে আপগ্রেড করেছি, তখন এটি কাজ করা বন্ধ করে দিয়েছে।

এখন, অন্য সম্পত্তি spring.jackson.default-property-inclusion=non_nullজাদু করছে।

আসলে, serialization-inclusionহ্রাস করা হয়। আমার ইন্টেলিজ আমাকে এটাই ছুড়ে মারে।

অবচিত: জ্যাকসন ২.7 এ অবজেক্টম্যাপার.সেটসরিয়ালাইজেশন অন্তর্ভুক্ত করা হয়েছে

সুতরাং, spring.jackson.default-property-inclusion=non_nullপরিবর্তে ব্যবহার শুরু করুন


4

আমি অন্য সমাধানে হোঁচট খেয়েছি, যা বেশ সুন্দর।

মূলত, উল্লিখিত পোস্ট করা ব্লগ থেকে কেবলমাত্র পদক্ষেপ 2 করুন এবং একটি কাস্টম অবজেক্টম্যাপারকে একটি বসন্ত হিসাবে সংজ্ঞায়িত করুন @Component। (আমি যখন পদক্ষেপ 3 থেকে সমস্ত টীকাগুলি মেঠোহ্যান্ডলার অ্যাডাপ্টার সামগ্রী সরিয়েছি তখন কাজ করা শুরু হয়েছিল )

@Component
@Primary
public class CustomObjectMapper extends ObjectMapper {
    public CustomObjectMapper() {
        setSerializationInclusion(JsonInclude.Include.NON_NULL); 
        configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 
    }
}

স্প্রিং দ্বারা স্ক্যান হওয়া প্যাকেজে যতক্ষণ না উপাদানটি কাজ করে। ( @Primaryআমার ক্ষেত্রে ব্যবহার করা বাধ্যতামূলক নয়, তবে কেন বিষয়গুলি স্পষ্ট করে তুলবেন না))

অন্যান্য পদ্ধতির তুলনায় আমার জন্য দুটি সুবিধা রয়েছে:

  • এটি সহজ; আমি জ্যাকসনের কাছ থেকে কেবল একটি ক্লাস বাড়িয়ে দিতে পারি এবং খুব স্প্রিং-নির্দিষ্ট স্টাফের মতো সম্পর্কে জানতে হবে না Jackson2ObjectMapperBuilder
  • আমি আমার অ্যাপ্লিকেশনটির অন্য একটি অংশে জেএসওনকে ডিসরিয়ালাইজ করার জন্য একই জ্যাকসন কনফিগার ব্যবহার করতে চাই এবং এইভাবে এটি খুব সহজ: new CustomObjectMapper()পরিবর্তে new ObjectMapper()

এই পদ্ধতির খারাপ দিকটি হ'ল ObjectMapperস্প্রিং বুট দ্বারা তৈরি বা কনফিগার করা কোনও দৃষ্টিতে আপনার কাস্টম কনফিগারেশন প্রয়োগ করা হবে না ।
অ্যান্ডি উইলকিনসন

হুম, কাস্টম কনফিগ হয় মধ্যে অন্তর্নিহিত ধারাবাহিকতাতে জন্য ব্যবহৃত @RestControllerশ্রেণীর যা বর্তমানে আমার জন্য আল্লাহই যথেষ্ট। (সুতরাং আপনার অর্থ হ'ল স্প্রিং বুট নয়, উদাহরণস্বরূপ স্প্রিং এমভিসি দ্বারা তৈরি করা হয়েছে?) তবে আমি যদি এমন অন্যান্য ক্ষেত্রেও চলে যাই যেখানে অবজেক্টম্যাপারদের তাত্ক্ষণিক হওয়া দরকার, আমি জ্যাকসন 2 ওজেক্টম্যাপারবিল্ডার পদ্ধতির কথা মাথায় রাখব!
জোনিক

3

আমি যখন বসন্ত বুট ২.০. in এ অবজেক্টম্যাপারটিকে প্রাথমিক করার চেষ্টা করেছি তখন আমার ত্রুটি হয়েছিল তাই আমি স্প্রিং বুটটি আমার জন্য তৈরি করেছিলাম

এছাড়াও https://stackoverflow.com/a/48519868/255139 দেখুন

@Lazy
@Autowired
ObjectMapper mapper;

@PostConstruct
public ObjectMapper configureMapper() {
    mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
    mapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);

    mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);

    mapper.configure(MapperFeature.ALLOW_COERCION_OF_SCALARS, true);
    mapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true);

    SimpleModule module = new SimpleModule();
    module.addDeserializer(LocalDate.class, new LocalDateDeserializer());
    module.addSerializer(LocalDate.class, new LocalDateSerializer());
    mapper.registerModule(module);

    return mapper;
}

1

আমি উপরে বর্ণিত সমাধানটি এর সাথে পেয়েছি:

বসন্ত.জ্যাকসন.সিরিয়ালাইজেশন-অন্তর্ভুক্তি = নন_নুল

কেবল বসন্ত বুটের 1.4.0.REREASE সংস্করণে শুরু করে কাজ করতে। অন্যান্য সমস্ত ক্ষেত্রে কনফিগারটি উপেক্ষা করা হয়।

আমি বসন্ত বুটের নমুনা "বসন্ত-বুট-নমুনা-জার্সি" এর একটি পরিবর্তন নিয়ে পরীক্ষা করে এটি যাচাই করেছি


0

আমি স্প্রিং বুটের জন্য জিজ্ঞাসা করা প্রশ্নটি জানি, তবে আমি বিশ্বাস করি যে প্রচুর লোক কীভাবে নন স্প্রিং বুটে এটি করতে পারে তা খুঁজছেন, যেমন আমার প্রায় পুরো দিন অনুসন্ধান করে।

স্প্রিং 4 এর উপরে, MappingJacksonHttpMessageConverterযদি আপনি কেবল কনফিগার করতে চান তবে কনফিগার করার দরকার নেই ObjectMapper

আপনার কেবল এটি করা দরকার:

public class MyObjectMapper extends ObjectMapper {

    private static final long serialVersionUID = 4219938065516862637L;

    public MyObjectMapper() {
        super();
        enable(SerializationFeature.INDENT_OUTPUT);
    }       
}

এবং আপনার বসন্ত কনফিগারেশনে, এই শিমটি তৈরি করুন:

@Bean 
public MyObjectMapper myObjectMapper() {        
    return new MyObjectMapper();
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.