2014-11-13 9 views
5

Opracowuję aplikację na Androida, która wyświetla okna dialogowe z niektórymi usługami sieciowymi Google App Engine.Jak naprawić niedokładne DateTime (minuty) analizowane w bibliotekach Jackson/Gson?

Ta aplikacja implementuje działanie na czacie, które ma bardzo prostą funkcję: wysłać tekst.

Podczas debugowania zauważyłem, że wiadomości, które wymieniłem na serwerze, nie były wyświetlane w tej samej kolejności, w jakiej wysłałem je w mojej aplikacji. Moją pierwszą myślą było, że problem pochodzi z serwera.

Początkowo sprawdziłem surowego JSON ja otrzymywał:

{ 
"messages": [ 
    { 
    "message": "test 3", 
    "author": "daniel", 
    "message_id": "5724160613416960", 
    "sent_at": "2014-11-13T09:42:42.861950" 
    }, 
    { 
    "message": "test 2", 
    "author": "daniel", 
    "message_id": "5649050225344512", 
    "sent_at": "2014-11-13T09:42:10.390960" 
    }, 
    { 
    "message": "test 1", 
    "author": "daniel", 
    "message_id": "5178081291534336", 
    "sent_at": "2014-11-13T09:41:01.998830" 
    } 
], 
"kind": "company#chatsItem", 
"etag": "\"RUCkC9XynEQNZ2t5E0aa41edXro/xRNtgkWIUbq4zCgmv2iq2fy-UIg\"" 
} 

Jak widać, dane surowe jest prawidłowo uporządkowane. Ale nadchodzi zabawna część. Kiedy dodać parsera JSON, takich jak JacksonFactory (lub nawet GsonFactory):

Company.Builder builder = new Company.Builder(AndroidHttp.newCompatibleTransport(), new JacksonFactory(), null); 
Company service = builder.build(); 
ChatsChatCollectionResponse response = service.chats().list(user_id, album_id, token).execute(); 
List<ChatsChatResponse> messagesResponse = response.getMessages(); 

Oto ChatsChatResponse przedmioty zamówione w taki sam sposób jak powyżej:

[0] = {[email protected]6} size = 4 
[0] = {[email protected]}"author" -> "daniel" 
[1] = {[email protected]}"message" -> "test 3" 
[2] = {[email protected]}"message_id" -> "5724160613416960" 
[3] = {[email protected]}"sent_at" -> "2014-11-13T10:57:03.950+01:00" 

[1] = {[email protected]6} size = 4 
[0] = {[email protected]}"author" -> "daniel" 
[1] = {[email protected]}"message" -> "test 2" 
[2] = {[email protected]}"message_id" -> "5649050225344512" 
[3] = {[email protected]}"sent_at" -> "2014-11-13T10:48:40.960+01:00" 

[2] = {[email protected]8} size = 4 
[0] = {[email protected]}"author" -> "daniel" 
[1] = {[email protected]}"message" -> "test 1" 
[2] = {[email protected]}"message_id" -> "5178081291534336" 
[3] = {[email protected]}"sent_at" -> "2014-11-13T10:57:39.830+01:00" 

dlaczego jest taki przypadkowy różnica w polu "sent_at"?

EDIT Zapomniałam wspomnieć, że ja nie mówię o przesunięciu 1 godzinę, która odpowiada czasowej, ale raczej o tym, jak są losowo minuty.

+0

mógłbyś zawierać definicję POJO dla 'ChatsChatResponse'? Ważne jest, aby wiedzieć, jakie typy danych są używane. Wygląda na to, że używasz deserializera opartego na Jackson, więc wersja Jacksona może również mieć znaczenie: możesz chcieć zweryfikować, używając również najnowszej wersji poprawki. – StaxMan

Odpowiedz

3

nie jestem pewien co do rozwiązania, ale wyjaśnienie wydaje się dość oczywiste: zmiana nie jest przypadkowa w ogóle, ale raczej spowodowane przez dodanie wszystko po przecinku jako milisekund.

Weź trzecią pozycję, na przykład:

2014-11-13T09:41:01.998830 

Najwyraźniej parser odczytuje to jako:

hours: 09 
minutes: 41 
seconds: 01 
milliseconds: 998830 

Od milisekund jest większa niż 1000, to kończy się przekształcony 998s 830ms, który kiedy rozliczanie za pełne minuty to 16m 38s 830ms. Stąd:

hours: 09 
minutes: 41 + 16 
seconds: 01 + 38 
milliseconds: 830 

która produkuje dokładnie wynik jesteś widzeniem (regulacja czasowa modulo):

2014-11-13T10:57:39.830+01:00 

Jeśli masz kontrolę nad wyjściem serwisowym (punkt ten nie jest całkiem jasne, ze sformułowania zapytania), najłatwiejszą metodą byłoby wypisanie tylko trzech cyfr po przecinku dziesiętnym (tj. zaokrąglanie w milisekundach zamiast w milionach). Na przykład będzie to 2014-11-13T09:41:01.999.

Możliwe może być także naprawienie tego samego w analizatorze składni, ale wymagałoby to nieco więcej badań (najlepiej idealnego problemu, który odwzorowuje problem).

1

spróbuj ustawić format daty zwyczaj jak

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

0

Jak zauważyłem @matiash, masz niestandardowy format daty zawierający mikrosekundy. Problem polega na tym, że SimpleDateFormat, używane przez Jacksona, incorrectly parses microseconds.

Aby złagodzić ten należy utworzyć niestandardową Deserializator że obcina mikrosekund do milisekund:

public class MicrosecondDateSerializer extends JsonDeserializer<Date> { 

    private static SimpleDateFormat formatter = 
    new SimpleDateFormat("dd-MM-yyyyThh:mm:ss:SSS"); 

    @Override 
    public Date deserialize(JsonParser jp, DeserializationContext ctxt) 
     throws IOException, JsonProcessingException { 

    ObjectCodec oc = jp.getCodec(); 
    JsonNode node = jp.getCodec().readTree(jp); 
    String dateString = node.get("sent_at").asText(); 
    String dateStringTruncated = dateString.substring(0, dateString.length() - 3); 

    return formatter.parse(dateStringTruncated); 
    } 
} 
Powiązane problemy