web-dev-qa-db-fra.com

com.google.gson.JsonSyntaxException lors d'une tentative d'analyse de Date/Time dans json

J'utilise RestTemplete pour obtenir les données JSON d'une api de repos et j'utilise Gson pour analyser les données du format JSON vers Object

Gson gson = new Gson();

restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new GsonHttpMessageConverter());
restTemplate.getMessageConverters().add(new StringHttpMessageConverter());

List<Appel> resultList = null;

resultList = Arrays.asList(restTemplate.getForObject(urlService, Appel[].class));

mais je reçois ce problème avec Date, que dois-je faire .. 

Could not read JSON: 1382828400000; nested exception is com.google.gson.JsonSyntaxException: 1382828400000

mon Pojo qui contient d'autres pojos dans son corps

public class Appel implements Serializable {

    private Integer numOrdre;
    private String reference;
    private String objet;
    private String organisme;
    private Double budget;
    private Double caution;
    private Date dateParution;
    private Date heureParution;
    private Date dateLimite;
    private Date heureLimite;
    private List<Support> supportList;
    private Ville villeid;
    private Categorie categorieid;

    public Appel() {
    }

    public Appel(Integer numOrdre, String reference, String objet, String organisme, Date dateParution, Date heureParution, Date dateLimite) {
        this.numOrdre = numOrdre;
        this.reference = reference;
        this.objet = objet;
        this.organisme = organisme;
        this.dateParution = dateParution;
        this.heureParution = heureParution;
        this.dateLimite = dateLimite;
    }

c'est ce json retourné par mon API 

[
   {
       "numOrdre": 918272,
       "reference": "some text",
       "objet": "some text",
       "organisme": "some text",
       "budget": 3000000,
       "caution": 3000000,
       "dateParution": 1382828400000,
       "heureParution": 59400000,
       "dateLimite": 1389657600000,
       "heureLimite": 34200000,
       "supportList":
       [
           {
               "id": 1,
               "nom": "some text",
               "dateSupport": 1384732800000,
               "pgCol": "013/01"
           },
           {
               "id": 2,
               "nom": "some text",
               "dateSupport": 1380236400000,
               "pgCol": "011/01"
           }
       ],
       "villeid":
       {
           "id": 2,
           "nom": "Ville",
           "paysid":
           {
               "id": 1,
               "nom": "Pays"
           }
       },
       "categorieid":
       {
           "id": 1,
           "description": "some text"
       }
   },
  .....
]
13
Noureddine

Ce que j’ai fait enfin est d’aller dans mon projet d’API et de créer un CustomSerializer. 

public class CustomDateSerializer extends JsonSerializer<Date> {  

    @Override
    public void serialize(Date t, JsonGenerator jg, SerializerProvider sp) throws IOException, JsonProcessingException {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        String formattedDate = formatter.format(t);

        jg.writeString(formattedDate);
    }
}

qui renvoient le format aaaa-MM-jj et moi annoté les champs de date avec

@JsonSerialize(using = CustomDateSerializer.class)

dans mon application Android, j'ai créé l'objet Gson 

            Reader reader = new InputStreamReader(content);

            GsonBuilder gsonBuilder = new GsonBuilder();
            gsonBuilder.setDateFormat("yyyy-MM-dd");
            Gson gson = gsonBuilder.create();
            appels = Arrays.asList(gson.fromJson(reader, Appel[].class));
            content.close();

et ça marche pour le moment .. merci pour votre aide je l'apprécie

6
Noureddine

Les sérialiseurs personnalisés ne sont plus nécessaires - utilisez simplement GsonBuilder et spécifiez le format de la date, comme suit:

Timestamp t = new Timestamp(System.currentTimeMillis());

String json = new GsonBuilder()
               .setDateFormat("yyyy-MM-dd hh:mm:ss.S")
               .create()
               .toJson(t);

System.out.println(json);
9
DiscDev

La valeur 1382828400000 est longue (durée en millisecondes). Vous dites à GSON que le champ est une Date et qu'il ne peut pas convertir automatiquement une long en une Date

Vous devez spécifier vos champs en tant que valeurs longues

private long dateParution;
private long heureParution;
private long dateLimite;
private long heureLimite;

et après que GSON ait jeté la chaîne JSON dans l'instance de classe Appel souhaitée, construisez un autre objet avec ces champs sous forme de dates et convertissez-les lors de l'affectation des valeurs au nouvel objet.

Une autre alternative consiste à implémenter votre propre désérialiseur personnalisé:

 public class CustomDateDeserializer extends DateDeserializer {
     @Override
     public Date deserialize(JsonParser jsonParser, DeserializationContext context) throws IOException, JsonProcessingException {
         // get the value from the JSON
         long timeInMilliseconds = Long.parseLong(jsonParser.getText());

         Calendar calendar = Calendar.getInstance();
         calendar.setTimeInMillis(timeInMilliseconds);
         return calendar.getTime();
     }
 }

Vous devez définir ce désérialiseur personnalisé sur les champs de votre choix, sur les méthodes de définition, comme:

@JsonDeserialize(using=CustomDateDeserializer.class)
public void setDateParution(Date dateParution) {
    this.dateParution = dateParution;
}
0
Raul Rene