জ্যাকসন জেএসওএন ম্যাপারের সাথে জাভা 8 জাভা.টাইমকে সিরিয়ালাইজ / ডিসাইরিয়ালাইজ করুন


221

আমি জাভা 8 লোকালডেটটাইমের সাথে জ্যাকসন জেএসন ম্যাপার কীভাবে ব্যবহার করব?

org.codehaus.jackson.map.JsonMappingException: JSON স্ট্রিং থেকে প্রকারের [সরল টাইপ, শ্রেণির java.time.LocalDateTime] মানটি ইনস্ট্যান্ট করতে পারে না; কোনও একক স্ট্রিং নির্মাণকারী / কারখানা পদ্ধতি নেই (রেফারেন্স চেইনের মাধ্যমে: মাইডিডিও ["ফিল্ড 1"] -> সাবডিটিও ["তারিখ"])


4
আপনি কি নিশ্চিত যে জসনের লোকালডেটটাইম মানচিত্র করতে চান? যতদূর আমি জানি, জেএসনের তারিখগুলির জন্য কোনও ফর্ম্যাট নেই, যদিও জাভাস্ক্রিপ্ট আইএসও -8601 ব্যবহার করে। সমস্যাটি হচ্ছে, লোকালডেটটাইমের কোনও টাইম জোন নেই ... সুতরাং, আপনি যদি তারিখ / সময় তথ্য প্রেরণের জন্য জেএসওএনকে মাধ্যম হিসাবে ব্যবহার করেন, ক্লায়েন্ট যদি সময় অঞ্চলটির অভাবকে ডিফল্ট ইউটিসি (বা এর নিজস্ব) হিসাবে ব্যাখ্যা করে তবে আপনি সমস্যায় পড়তে পারেন সময় অঞ্চল). যদি আপনি এটি করতে চান তবে অবশ্যই এটি ঠিক আছে। তবে এর পরিবর্তে আপনি জোনেডেটটাইম ব্যবহারের কথা বিবেচনা করেছেন কিনা তা পরীক্ষা করে দেখুন
arcuri82

উত্তর:


276

এখানে কাস্টম সিরিয়ালাইজার / ডিসরিয়ালাইজার ব্যবহার করার দরকার নেই। ব্যবহারের জ্যাকসন-মডিউল-java8 DATETIME মডিউল এর :

জ্যাকসন জাভা 8 তারিখ এবং সময় এপিআই ডেটা ধরণের (জেএসআর -310) সনাক্ত করতে ডেটাটাইপ মডিউল।

এই মডিউলটি বেশ কয়েকটি শ্রেণীর জন্য সমর্থন যোগ করে:

  • স্থিতিকাল
  • তাত্ক্ষনিক
  • LocalDateTime
  • LOCALDATE
  • স্থানীয় সময়
  • মাস দিন
  • OffsetDateTime
  • OffsetTime
  • কাল
  • বছর
  • YearMonth
  • ZonedDateTime
  • ZoneId
  • ZoneOffset

59
হ্যাঁ! আমি যদিও এটি কাজ করছিলাম না কারণ আমি বুঝতে পারি নি যে ম্যাপার অবজেক্টটিতে এই কাস্টমাইজেশনটির একটি অবশ্যই করতে হবে: registerModule(new JSR310Module())বা findAndRegisterModules()Github.com/FasterXML/jackson-datatype-jsr310 দেখুন এবং আপনি স্প্রিং ফ্রেমওয়ার্ক ব্যবহার করেন তবে আপনার ম্যাপার অবজেক্টটি কীভাবে কাস্টমাইজ করতে হবে তা এখানে রয়েছে: stackoverflow.com/questions/7854030/…
আলেকজান্ডার টেলর

10
আমি চেষ্টা করেছি এমন সাধারণের সাথে কাজ করে না,OffsetDateTime @Test public void testJacksonOffsetDateTimeDeserializer() throws IOException { ObjectMapper mapper = new ObjectMapper().registerModule(new JavaTimeModule()); String json = "\"2015-10-20T11:00:00-8:30\""; mapper.readValue(json, OffsetDateTime.class); }
অভিজিৎ সরকার

9
আপনি যদি সাম্প্রতিক স্প্রিং ফ্রেমওয়ার্ক ব্যবহার করেন তবে নিজেকে কাস্টমাইজ করার জন্য আর প্রয়োজন নেই, যেমন জ্যাকসন মডিউলগুলি যেমন ক্লাসপথে
ভোরবার্গার

36
জেএসআর ৩১০ মডেলটি ইতিমধ্যে কিছুটা পুরানো, তার পরিবর্তে জাভাটাইমমডুল ব্যবহার করুন
জ্যাকব একেল

17
@MattBall আমি যে যোগ জ্যাকসন-ডাটাটাইপ-jsr310 ব্যবহারের ক্ষেত্রে সুপারিশ করবে, আপনি আপনার অবজেক্ট ম্যাপার সঙ্গে JavaTimeModule রেজিস্টার করতে হবে: objectMapper.registerModule(new JavaTimeModule());। সিরিয়ালাইজেশন এবং deserialization উভয় উপর।
গ্র্যান্ডএডমিরাল

76

আপডেট: answerতিহাসিক কারণে এই উত্তরটি রেখে দিচ্ছি, তবে আমি এটির প্রস্তাব দিই না। উপরে গৃহীত উত্তর দেখুন দয়া করে।

জ্যাকসনকে আপনার কাস্টম [ডি] সিরিয়ালাইজেশন ক্লাস ব্যবহার করে মানচিত্র করতে বলুন:

@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
private LocalDateTime ignoreUntil;

কাস্টম ক্লাস সরবরাহ:

public class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {
    @Override
    public void serialize(LocalDateTime arg0, JsonGenerator arg1, SerializerProvider arg2) throws IOException {
        arg1.writeString(arg0.toString());
    }
}

public class LocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
    @Override
    public LocalDateTime deserialize(JsonParser arg0, DeserializationContext arg1) throws IOException {
        return LocalDateTime.parse(arg0.getText());
    }
}

এলোমেলো সত্য: আমি যদি ক্লাসের উপরে বাসা বেঁধে রাখি এবং এগুলি স্থির না করি, ত্রুটি বার্তাটি অদ্ভুত: org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/json;charset=UTF-8' not supported


এই লেখার হিসাবে, এখানে অন্যান্য উত্তরের একমাত্র সুবিধাটি ফারস্টারএক্সএমএল উপর নির্ভর করে না, যাই হোক না কেন।
আলেকজান্ডার টেলর

4
দ্রুততম এক্সএমএল হলেন জ্যাকসন। quickxML.com github.com/fasterxml/jackson
ম্যাট বল

4
আচ্ছা বুঝলাম. আমি যে প্রকল্পে কাজ করছি তাতে অনেক প্রাচীন পম এন্ট্রি রয়েছে। org.codehaus আর নেই, এখন সব com.fasterxML। ধন্যবাদ!
আলেকজান্ডার টেলর

2
এছাড়াও আমি বিল্ট-ইনটি ব্যবহার করতে পারিনি কারণ আমার আইএসও_ড্যাটালটাইম ফর্ম্যাটারটি পাস করতে হবে। জেএসআর 310 মডুল ব্যবহার করার সময় এটি করা সম্ভব কিনা তা নিশ্চিত নন।
isaac.hazan

স্প্রিংয়ের সাথে এটি ব্যবহার করে আমাকে দুজনের একটি সিম তৈরি করতে হয়েছিল LocalDateTimeSerializerএবংLocalDateTimeDeserializer
বেনআর

53

আপনি যদি ফাস্টেক্সএমএল এর অবজেক্টম্যাপার ক্লাস ব্যবহার করছেন তবে ডিফল্টরূপে অবজেক্টম্যাপার লোকালডেটটাইম ক্লাসটি বুঝতে পারে না, সুতরাং আপনার গ্রেড / ম্যাভেনে আপনাকে আরও একটি নির্ভরতা যুক্ত করতে হবে:

compile 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.7.3'

এখন আপনাকে এই লাইব্রেরি দ্বারা প্রদত্ত ডেটাটাইপ সমর্থনটি আপনার অবজেক্টম্যাপার অবজেক্টে নিবন্ধিত করতে হবে, এটি অনুসরণ করে করা যেতে পারে:

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.findAndRegisterModules();

এখন, আপনার জসনস্ট্রিংয়ে, আপনি সহজেই আপনার জাভা.লোক্যালডেটটাইম ক্ষেত্রটি নীচের মতো রাখতে পারেন:

{
    "user_id": 1,
    "score": 9,
    "date_time": "2016-05-28T17:39:44.937"
}

এই সমস্ত কিছু করার মাধ্যমে, আপনার জাসন ফাইলটি জাভা অবজেক্ট রূপান্তরটিতে দুর্দান্ত কাজ করবে, আপনি নিম্নলিখিতটি ফাইল পড়তে পারেন:

objectMapper.readValue(jsonString, new TypeReference<List<User>>() {
            });

4
findAndRegisterModules()সমালোচকদের টুকরা আমার জন্য অনুপস্থিত ছিল যখন একটি নির্মাণের ছিলObjectMapper
Xaero Degreaz

2
তাত্ক্ষণিক সম্পর্কে কি?
পাউডার366

1
আমি এই লাইনটিও যুক্ত করেছি: objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
জেনেট

এটি প্রয়োজনীয় সম্পূর্ণ কোড: অবজেক্টম্যাপার অবজেক্টম্যাপার = নতুন অবজেক্টম্যাপার (); objectMapper.findAndRegisterModules (); অবজেক্টম্যাপার.কনফিগুরে (সিরিয়ালাইজেশন ফিচার। WRITE_DATES_AS_TIMESTAMPS, মিথ্যা);
খুশ

42

এই মাভেন নির্ভরতা আপনার সমস্যার সমাধান করবে:

<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
    <version>2.6.5</version>
</dependency>

একটি জিনিস আমি সংগ্রাম করেছিলাম যে জোনডেটটাইম টাইমজোনটি ডিসিরিয়ালেসনের সময় GMT তে পরিবর্তন করা হয়েছিল। দেখা গেল, ডিফল্টরূপে জ্যাকসন এটিকে প্রসঙ্গ থেকে একটিকে প্রতিস্থাপন করে .. অঞ্চল ধরে রাখতে হলে অবশ্যই এই 'বৈশিষ্ট্যটি' অক্ষম করতে হবে

Jackson2ObjectMapperBuilder.json()
    .featuresToDisable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE)

5
DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE ইঙ্গিতের জন্য অনেক ধন্যবাদ।
আন্দ্রেই উরভান্তেসেভ

5
নিষ্ক্রিয় করার পাশাপাশি সবকিছুকে যেমন করা উচিত ঠিক তেমন কাজ শুরু করার জন্য DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONEআমাকেও অক্ষম করতে হয়েছিল SerializationFeature.WRITE_DATES_AS_TIMESTAMPS
ম্যাট ওয়াটসন

16

স্প্রিং বুট ব্যবহার করার সময় আমারও একই সমস্যা ছিল । স্প্রিং বুটের সাথে 1.5.1. কেবলমাত্র আমাকে যা করতে হয়েছিল তা হ'ল নির্ভরতা যুক্ত করা:

<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
</dependency>

7

আপনি যদি জার্সি ব্যবহার করছেন তবে অন্যদের পরামর্শ অনুসারে আপনাকে ম্যাভেন নির্ভরতা (জ্যাকসন-ডেটাটাইপ-জেএসআর 310) যুক্ত করতে হবে এবং আপনার অবজেক্ট ম্যাপার উদাহরণটি এভাবে রেজিস্টার করতে হবে:

@Provider
public class JacksonObjectMapper implements ContextResolver<ObjectMapper> {

  final ObjectMapper defaultObjectMapper;

  public JacksonObjectMapper() {
    defaultObjectMapper = createDefaultMapper();
  }

  @Override
  public ObjectMapper getContext(Class<?> type) {
    return defaultObjectMapper;
  }

  private static ObjectMapper createDefaultMapper() {
    final ObjectMapper mapper = new ObjectMapper();    
    mapper.registerModule(new JavaTimeModule());
    return mapper;
  }
}

আপনার সংস্থানগুলিতে জ্যাকসনকে নিবন্ধভুক্ত করার সময়, আপনাকে এই ম্যাপারটি এভাবে যুক্ত করতে হবে:

final ResourceConfig rc = new ResourceConfig().packages("<your package>");
rc
  .register(JacksonObjectMapper.class)
  .register(JacksonJaxbJsonProvider.class);

6

আপনি ব্যবহার না পারেন, তাহলে jackson-modules-java8যাই হোক না কেন কারণে আপনি (অব-) ধারাবাহিকভাবে করতে তাত্ক্ষণিক ক্ষেত্র longব্যবহার @JsonIgnoreএবং @JsonGetter& @JsonSetter:

public class MyBean {

    private Instant time = Instant.now();

    @JsonIgnore
    public Instant getTime() {
        return this.time;
    }

    public void setTime(Instant time) {
        this.time = time;
    }

    @JsonGetter
    private long getEpochTime() {
        return this.time.toEpochMilli();
    }

    @JsonSetter
    private void setEpochTime(long time) {
        this.time = Instant.ofEpochMilli(time);
    }
}

উদাহরণ:

@Test
public void testJsonTime() throws Exception {
    String json = new ObjectMapper().writeValueAsString(new MyBean());
    System.out.println(json);
    MyBean myBean = new ObjectMapper().readValue(json, MyBean.class);
    System.out.println(myBean.getTime());
}

উৎপাদনের

{"epochTime":1506432517242}
2017-09-26T13:28:37.242Z

এটি একটি খুব পরিষ্কার পদ্ধতি এবং আপনার শ্রেণীর ব্যবহারকারীরা যেভাবে চান তা ব্যবহার করতে দেয়।
আশার হাসান

3

আমি এই সময়ের ফর্ম্যাটটি ব্যবহার করি: "{birthDate": "2018-05-24T13:56:13Z}"json.time.Instant এ json থেকে deserialize করতে (স্ক্রিনশট দেখুন)

এখানে চিত্র বর্ণনা লিখুন


3

এটি কেবলমাত্র একটি ইউনিট পরীক্ষায় এটি কীভাবে ব্যবহার করবেন তা এই উদাহরণটি যা আমি এই সমস্যাটি ডিবাগ করতে হ্যাক করেছি। মূল উপাদানগুলি হ'ল

  • mapper.registerModule(new JavaTimeModule());
  • মাভেন নির্ভরতা <artifactId>jackson-datatype-jsr310</artifactId>

কোড:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.testng.Assert;
import org.testng.annotations.Test;

import java.io.IOException;
import java.io.Serializable;
import java.time.Instant;

class Mumu implements Serializable {
    private Instant from;
    private String text;

    Mumu(Instant from, String text) {
        this.from = from;
        this.text = text;
    }

    public Mumu() {
    }

    public Instant getFrom() {
        return from;
    }

    public String getText() {
        return text;
    }

    @Override
    public String toString() {
        return "Mumu{" +
                "from=" + from +
                ", text='" + text + '\'' +
                '}';
    }
}
public class Scratch {


    @Test
    public void JacksonInstant() throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(new JavaTimeModule());

        Mumu before = new Mumu(Instant.now(), "before");
        String jsonInString = mapper.writeValueAsString(before);


        System.out.println("-- BEFORE --");
        System.out.println(before);
        System.out.println(jsonInString);

        Mumu after = mapper.readValue(jsonInString, Mumu.class);
        System.out.println("-- AFTER --");
        System.out.println(after);

        Assert.assertEquals(after.toString(), before.toString());
    }

}

2

আপনি যদি স্প্রিং বুট ব্যবহার করে থাকেন এবং অফসেটডেটটাইমে এই সমস্যাটি থাকে তবে উপরে @greperror দ্বারা উত্তর হিসাবে রেজিস্টারমডুলগুলি ব্যবহার করতে হবে (মে 28 '16 তে 13:04 তে উত্তর দিয়েছেন) তবে লক্ষ্য করুন যে এর মধ্যে একটি পার্থক্য রয়েছে। উল্লিখিত নির্ভরতা যুক্ত করার দরকার নেই কারণ আমি অনুমান করছি যে স্প্রিং বুটটি ইতিমধ্যে রয়েছে। আমি স্প্রিং বুটের সাথে এই সমস্যাটি নিয়ে আসছিলাম এবং এটি নির্ভরতা যুক্ত না করে এটি আমার পক্ষে কাজ করে।


1

application.ymlতাত্ক্ষণিক সময় সমাধানের জন্য আপনি এটি আপনার ফাইলে সেট করতে পারেন যা জাভা 8-এ তারিখের এপিআই:

spring.jackson.serialization.write-dates-as-timestamps=false

1

যারা স্প্রিং বুট 2.x ব্যবহার করেন তাদের জন্য

উপরের কোনও কিছুই করার দরকার নেই - জাভা 8 লোকালডেটটাইমটি বাক্সের বাইরে সিরিয়ালযুক্ত / ডি-সিরিয়ালাইজড। আমাকে উপরের সমস্তটি 1.x তে করতে হয়েছিল তবে বুট ২.x সহ এটি নির্বিঘ্নে কাজ করে।

স্প্রিং বুটে JSON জাভা 8 লোকালডেটটাইম ফর্ম্যাটটিও এই রেফারেন্সটি দেখুন


1

SpringBootএখানে ব্যবহারের সময় যদি কারও সমস্যা হয় তবে আমি কীভাবে নতুন নির্ভরতা যুক্ত না করেই সমস্যাটি সমাধান করেছি।

ইন Spring 2.1.3জ্যাকসন তারিখের স্ট্রিংকে আশা 2019-05-21T07:37:11.000এই yyyy-MM-dd HH:mm:ss.SSSযে ডি ধারাবাহিকভাবে করতে বিন্যাস LocalDateTime। নিশ্চিত করুন তারিখ স্ট্রিং সঙ্গে তারিখ এবং সময় আলাদা Tনা দিয়ে space। সেকেন্ড ( ss) এবং মিলিসেকেন্ড ( SSS) বাদ দেওয়া যেতে পারে।

@JsonProperty("last_charge_date")
public LocalDateTime lastChargeDate;

0

আপনি যদি ফাস্টজসন ব্যবহারের কথা বিবেচনা করেন তবে আপনি আপনার সমস্যার সমাধান করতে পারেন, সংস্করণটি নোট করুন

 <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.56</version>
 </dependency>

0

আপনার যদি গ্রাফকিউএল জাভা সরঞ্জামগুলির কারণে সমস্যাটি হচ্ছে এবং Instantএকটি তারিখের স্ট্রিং থেকে একটি জাভা মার্শাল করার চেষ্টা করছেন তবে আপনাকে নির্দিষ্ট কনফিগারেশনের সাথে একটি অবজেক্টম্যাপার ব্যবহার করতে আপনার স্কিমাপার্সার সেটআপ করতে হবে:

আপনার গ্রাফকিউএসএলএসএইচ বিল্ডার শ্রেণিতে, অবজেক্টম্যাপার ইনজেকশন করুন এবং এই মডিউলগুলি যুক্ত করুন:

        ObjectMapper objectMapper = 
    new ObjectMapper().registerModule(new JavaTimeModule())
            .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);

এবং এটি বিকল্পগুলিতে যুক্ত করুন:

final SchemaParserOptions options = SchemaParserOptions.newOptions()
            .objectMapperProvider(fieldDefinition -> objectMapper)
            .typeDefinitionFactory(new YourTypeDefinitionFactory())
            .build();

দেখুন https://github.com/graphql-java-kickstart/graphql-spring-boot/issues/32


0

আপনি যদি জ্যাকসন সিরিয়ালাইজার ব্যবহার করছেন তবে তারিখের মডিউলগুলি ব্যবহারের একটি উপায় এখানে রয়েছে:

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.module.paramnames.ParameterNamesModule;
import org.apache.kafka.common.serialization.Serializer;

public class JacksonSerializer<T> implements Serializer<T> {

    private final ObjectMapper mapper = new ObjectMapper()
            .registerModule(new ParameterNamesModule())
            .registerModule(new Jdk8Module())
            .registerModule(new JavaTimeModule());

    @Override
    public byte[] serialize(String s, T object) {
        try {
            return mapper.writeValueAsBytes(object);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return null;
    }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.