जीआरएन स्ट्रिंग से java.util.date में रेट्रोफिट जीएसओएन क्रमबद्ध करें


83

मैं अपने REST कॉल के लिए रेट्रोफिट लाइब्रेरी का उपयोग कर रहा हूं। मैंने जो कुछ किया है, उसमें से अधिकांश मक्खन के रूप में चिकनी है, लेकिन किसी कारण से मैं JSON टाइमस्टैम्प स्ट्रिंग्स को java.util.Dateऑब्जेक्ट्स में परिवर्तित करने में समस्या हो रही है। JSON जो इस तरह से आ रहा है।

{
    "date": "2013-07-16",
    "created_at": "2013-07-16T22:52:36Z",
} 

मैं इन स्ट्रिंग्स को बदलने के लिए रेट्रोफिट या ग्सन को कैसे बता सकता हूं java.util.Date objects?


इस प्रश्न का एक डुप्लिकेट जैसा लगता है ।
दावमार्टल

@Davmrtl: दो अलग-अलग तारीखों के प्रारूप यहां होने के बाद से यह समान नहीं है। इसलिए इसे एक अलग दृष्टिकोण की आवश्यकता है।
giampaolo

जवाबों:


166
Gson gson = new GsonBuilder()
    .setDateFormat("yyyy-MM-dd'T'HH:mm:ss")
    .create();

RestAdapter restAdapter = new RestAdapter.Builder()
    .setEndpoint(API_BASE_URL)
    .setConverter(new GsonConverter.create(gson))
    .build();

या कोटलिन समकक्ष:

val gson = GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ss").create()
RestAdapter restAdapter = Retrofit.Builder()
    .baseUrl(API_BASE_URL)
    .addConverterFactory(GsonConverterFactory.create(gson))
    .build()
    .create(T::class.java)

आप अपने कस्टमाइज़्ड Gson पार्सर को रेट्रोफिट पर सेट कर सकते हैं। यहाँ और अधिक: रेट्रोफ़िट वेबसाइट

Ondreju की प्रतिक्रिया को देखें कि रेट्रोफिट 2 में इसे कैसे लागू किया जाए।


8
कृपया अपने कोड को संक्षेप में समझाएं ताकि यह ओपी और अन्य पाठकों के लिए अधिक उपयोगी हो।
मोहित जैन

मैं अपने सभी अनुरोधों के लिए यह कैसे कर सकता हूं? तो इसे मेरे लिए जोड़ें ServiceGenerator?
Zapnologica

4
यह वास्तव में मेरे लिए स्थान लागू नहीं करता है। 2016-02-11T13:42:14.401Zएक दिनांक ऑब्जेक्ट के लिए deserialized हो जाता है जो 13:42:14मेरे लोकेल में है।
अलिर्ज़ा मिरियन

मैंने यह कोशिश की है, डाउनलोड की गई चीजें अब काम करने लगती हैं। लेकिन जब मैं सर्वर पर एक Json ऑब्जेक्ट पोस्ट करता हूं। क्या यह मेरे समय क्षेत्र को हटा देगा?
Zapnologica

मैंने इस समाधान को लागू करने के बाद बिना किसी कारण के साथ अपने ऐप को क्रैश करने की समस्या का पता लगाने के लिए इतना समय बिताया। जब मैं नकल की और देते प्रारूप पेस्ट कुछ से एक उद्धरण चिह्न बदल 'टी' के लिए 'टी' - वहाँ है एक अलग - घड़ी ध्यान से!
लुकासटार्ज़ास्का

86

@ gderaco का उत्तर 2.0 अपडेट करने के लिए अपडेट किया गया:

Gson gson = new GsonBuilder()
.setDateFormat("yyyy-MM-dd'T'HH:mm:ss")
.create();

Retrofit retrofitAdapter = new Retrofit.Builder()
.baseUrl(API_BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.build();

2
दिनांक प्रारूप को कॉपी करते समय उद्धरण चिह्न के लिए देखें - मुझे इसके साथ समस्या थी!
लुकासटार्ज़ास्का

14

यहाँ देखें कि मैंने यह कैसे किया:

दिनांक समय बढ़ाते हुए DateTime वर्ग बनाएँ और फिर एक कस्टम डिजायरलाइज़र लिखें:

public class DateTime extends java.util.Date {

    public DateTime(long readLong) {
        super(readLong);
    }

    public DateTime(Date date) {
        super(date.getTime());
    }       
}

अब deserializer भाग के लिए जहां हम Date और DateTime कन्वर्टर्स दोनों को पंजीकृत करते हैं:

public static Gson gsonWithDate(){
    final GsonBuilder builder = new GsonBuilder();

    builder.registerTypeAdapter(Date.class, new JsonDeserializer<Date>() {  

        final DateFormat df = new SimpleDateFormat("yyyy-MM-dd");  
        @Override  
        public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {  
            try {  
                return df.parse(json.getAsString());  
            } catch (final java.text.ParseException e) {  
                e.printStackTrace();  
                return null;  
            }  
        }
    });

    builder.registerTypeAdapter(DateTime.class, new JsonDeserializer<DateTime>() {  

        final DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
        @Override  
        public DateTime deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {  
            try {  
                return new DateTime(df.parse(json.getAsString()));  
            } catch (final java.text.ParseException e) {
                e.printStackTrace();  
                return null;  
            }  
        }
    });

    return builder.create();
}

और जब आप अपना रेस्टैप एडाप्टर बनाएँ, तो निम्न कार्य करें:

new RestAdapter.Builder().setConverter(gsonWithDate());

आपका फू इस तरह दिखना चाहिए:

class Foo {
    Date date;
    DateTime created_at;
}

धन्यवाद! मैं केवल से परिवर्तन करना पड़ा return df.parse(json.getAsString()); करने के लिए long timeStamp = Long.parseLong(json.getAsString()); return new java.util.Date(timeStamp);
जुआन Saravia

महान! धन्यवाद!
निकुंचेक ऑग

7

यदि कस्टम प्रारूप के साथ पार्सिंग संभव नहीं है, तो Gson केवल एक डेटाइम प्रारूप (बिल्डर में निर्दिष्ट) प्लस iso8601 को संभाल सकता है। तो, एक समाधान अपने कस्टम deserializer लिखने के लिए हो सकता है। आपकी समस्या को हल करने के लिए मैंने परिभाषित किया:

package stackoverflow.questions.q18473011;

import java.util.Date;

public class Foo {

    Date date;
    Date created_at;

    public Foo(Date date, Date created_at){
       this.date = date;
       this.created_at = created_at;
    }

    @Override
    public String toString() {
       return "Foo [date=" + date + ", created_at=" + created_at + "]";
    }

}

इस deserializer के साथ:

package stackoverflow.questions.q18473011;

import java.lang.reflect.Type;
import java.text.*;
import java.util.Date;

import com.google.gson.*;

public class FooDeserializer implements JsonDeserializer<Foo> {

     public Foo deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {

        String a = json.getAsJsonObject().get("date").getAsString();
        String b = json.getAsJsonObject().get("created_at").getAsString();

        SimpleDateFormat sdfDate = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat sdfDateWithTime = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");

        Date date, created;
        try {
           date = sdfDate.parse(a);
           created = sdfDateWithTime.parse(b);
        } catch (ParseException e) {
           throw new RuntimeException(e);
        }

        return new Foo(date, created);
    }

}

अंतिम चरण Gsonसही एडाप्टर के साथ एक उदाहरण बनाना है :

package stackoverflow.questions.q18473011;

import com.google.gson.*;

public class Question {

    /**
     * @param args
     */
    public static void main(String[] args) {
      String s = "{ \"date\": \"2013-07-16\",    \"created_at\": \"2013-07-16T22:52:36Z\"}";


      GsonBuilder builder = new GsonBuilder();
      builder.registerTypeAdapter(Foo.class, new FooDeserializer());

      Gson gson = builder.create();
      Foo myObject = gson.fromJson(s, Foo.class);

      System.out.println("Result: "+myObject);
    }

}

मेरा परिणाम:

Result: Foo [date=Tue Jul 16 00:00:00 CEST 2013, created_at=Tue Jul 16 22:52:36 CEST 2013]

1
क्या होगा यदि मेरे पास फू (कस्टम वस्तुओं सहित) के अंदर 15-20 क्षेत्र हैं, तो मुझे उन्हें मैन्युअल रूप से सही करना होगा। यह तो Gson के उद्देश्य को मारता है।
फरीद

1

काफी शाब्दिक रूप से यदि आपके पास पहले से ही बनाई गई कक्षा में "create_at" नाम के साथ एक दिनांक ऑब्जेक्ट है तो यह आसान है:

Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").create();
YourObject parsedObject1 = gson.fromJson(JsonStringYouGotSomehow, YourObject.class);

और आपने कल लिया। कोई जटिल ओवरराइडिंग की जरूरत नहीं है।


आपको इसे पहले "पहले रिट्रोफिट" के साथ आज़माना चाहिए था और आप कर रहे हैं। कोई जटिल ओवरराइडिंग की आवश्यकता नहीं है।
फरीद

1

आप इस तरह दो नई कक्षाओं को परिभाषित कर सकते हैं:

import java.util.Date;

public class MyDate extends Date {
}

तथा

import java.util.Date;

public class CreatedAtDate extends Date {
}

आपका POJO इस तरह होगा:

import MyDate;
import CreatedAtDate;

public class Foo {
    MyDate date;
    CreatedAtDate created_at;
}

अंत में अपने कस्टम deserializer सेट करें:

public class MyDateDeserializer implements JsonDeserializer<Date> {

    public static final SimpleDateFormat sServerDateDateFormat = new SimpleDateFormat("yyyy-MM-dd");

    @Override
    public MyDate deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
         if (json != null) {
            final String jsonString = json.getAsString();
            try {
                return (MyDate) sServerDateDateFormat.parse(jsonString);
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}

तथा

GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(MyDate.class, new MyDateDeserializer());

0

यह सीधे पूछे गए प्रश्न का उत्तर नहीं देता है, लेकिन मेरी राय में "कला की स्थिति" है यदि कोडर को समस्या को हल करने के तरीके पर पूर्ण स्वतंत्रता है।

सबसे पहले, यह java.util.Date का उपयोग करने के लिए सबसे अच्छा समाधान नहीं है। कारण यह है कि उन वर्गों के पास कुछ कोने के मामलों में कोई आदर्श व्यवहार नहीं था, जहां जावा इंस्टेंट क्लास आदि द्वारा सुपरसाइड किए गए थे, तो एसओ प्रश्न में बेसिल बोर्क के उत्तर की जांच करें: एपीआई स्तर के लिए कोटलिन में दिनांक ऑब्जेक्ट बनाना 16 से कम या उसके बराबर

इसलिए मैंने एंड्रॉइड पर तीनटैनबप के इंस्टेंट क्लास का उपयोग किया, और कोटलिन का उपयोग किया:

val gson = GsonBuilder().registerTypeAdapter(Instant::class.java,
    JsonDeserializer<Instant> { json: JsonElement, _: Type?, _: JsonDeserializationContext? ->
        ZonedDateTime.parse(
            json.asJsonPrimitive.asString
        ).toInstant()
    }
).create()

val retrofit = Retrofit.Builder()
    .baseUrl(baseUrl)
    .addConverterFactory(GsonConverterFactory.create(gson))
    .build()
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.