J'ai une demande écrite en Java avec Spring Boot et Spring MVC qui répond à une requête get avec un objet qui contient un tableau d'octets:Confus par JSON Spring sérialisation
public HashedPasswordSpec get() {
User user = userRepository.findByEmail("[email protected]");
return user.getHashedPasswordSpec();
}
sur le côté client je tente de désérialiser automatiquement en utilisant la même classe:
RestTemplate restTemplate = new RestTemplate();
HashedPasswordSpec spec = restTemplate.getForObject("http://localhost:8080/v1/hashed-password-spec", HashedPasswordSpec.class);
qui échoue avec cette erreur:
Caused by: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was STRING at line 1 column 10 path $.salt
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:224)
at com.google.gson.Gson.fromJson(Gson.java:887)
at com.google.gson.Gson.fromJson(Gson.java:852)
at org.springframework.http.converter.json.GsonHttpMessageConverter.readTypeToken(GsonHttpMessageConverter.java:161)
... 39 more
Caused by: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was STRING at line 1 column 10 path $.salt
at com.google.gson.stream.JsonReader.beginArray(JsonReader.java:350)
at com.google.gson.internal.bind.ArrayTypeAdapter.read(ArrayTypeAdapter.java:70)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:129)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:220)
... 42 more
salt
est le byte[]
. Quand je hériterez d'une chaîne et l'imprimer:
String spec = restTemplate.getForObject("http://localhost:8080/v1/hashed-password-spec", String.class);
System.out.println(spec);
Je vois ceci:
{"salt":"2GKm9SVxsvLmwaydk8heK/eB94HoPR21+2rTmKMjWo0=","algorithm":"SCrypt","cost":12,"blockSize":8,"parallelization":1,"keyLength":256}
Comme vous pouvez le voir, le sel est sérialisé comme base64, mais ce n'est pas ce que Gson fait hors de la boîte avec des tableaux d'octets. Est-ce que Spring Boot étend Gson pour sérialiser les tableaux d'octets en tant que chaînes Base64? Si oui, RestTemplate omet-il cette extension? Sont-ils incompatibles les uns avec les autres? Qu'est-ce que j'oublie ici?
Spring enregistre les sérialiseurs/désérialiseurs par défaut en fonction de ce qui se trouve dans le chemin de classe. Est-ce que le classpath de votre serveur contient Jackson? Votre classpath client contient-il uniquement Gson? –
@SotiriosDelimanolis: à la fois le serveur et le client contiennent Gson dans le classpath, mais pas directement, à travers une autre dépendance. Je ne suis pas sûr de Jackson. – Pablo
Jackson, par défaut, sérialise 'byte []' en base64, iirc. Gson ne le fait pas. Donc, votre serveur a probablement Jackson sur son classpath (qui est plus élevé dans son ordre d'enregistrement pour les sérialiseurs que Gson). –