J'essaie d'inclure du JSON brut dans un objet Java lorsque l'objet est (dé) sérialisé à l'aide de Jackson. Afin de tester cette fonctionnalité, j'ai écrit le test suivant:
public static class Pojo {
public String foo;
@JsonRawValue
public String bar;
}
@Test
public void test() throws JsonGenerationException, JsonMappingException, IOException {
String foo = "one";
String bar = "{\"A\":false}";
Pojo pojo = new Pojo();
pojo.foo = foo;
pojo.bar = bar;
String json = "{\"foo\":\"" + foo + "\",\"bar\":" + bar + "}";
ObjectMapper objectMapper = new ObjectMapper();
String output = objectMapper.writeValueAsString(pojo);
System.out.println(output);
assertEquals(json, output);
Pojo deserialized = objectMapper.readValue(output, Pojo.class);
assertEquals(foo, deserialized.foo);
assertEquals(bar, deserialized.bar);
}
Le code génère la ligne suivante:
{"foo":"one","bar":{"A":false}}
Le JSON est exactement ce à quoi je veux que les choses ressemblent. Malheureusement, le code échoue avec une exception lors de la tentative de lecture du JSON dans l'objet. Voici l'exception:
org.codehaus.jackson.map.JsonMappingException: impossible de désérialiser l'instance de java.lang.String à partir du jeton START_OBJECT à [Source: java.io.StringReader@d70d7a; ligne: 1, colonne: 13] (via la chaîne de référence: com.tnal.prism.cobalt.gather.testing.Pojo ["bar"])
Pourquoi Jackson fonctionne-t-il très bien dans une direction mais échoue dans l'autre direction? Il semble qu'il devrait être capable de reprendre sa propre sortie comme entrée. Je sais que ce que j'essaie de faire est peu orthodoxe (le conseil général est de créer un objet interne pour bar
qui a une propriété nommée A
), mais je ne veux pas du tout interagir avec ce JSON. Mon code agit comme un pass-through pour ce code - je veux récupérer ce JSON et le renvoyer sans rien toucher, car lorsque le JSON change, je ne veux pas que mon code ait besoin de modifications.
Merci pour le conseil.
EDIT: Fait de Pojo une classe statique, ce qui provoquait une erreur différente.
la source
Suite à la réponse de @StaxMan , j'ai réalisé les œuvres suivantes comme un charme:
Et, pour être fidèle à la question initiale, voici le test de fonctionnement:
la source
getJson()
revient unString
après tout. S'il retournait simplement leJsonNode
qui a été défini via le setter, il serait sérialisé comme vous le souhaitez, non?node.asText()
renvoie la valeur vide opposéetoString()
.J'ai pu le faire avec un désérialiseur personnalisé (coupé et collé à partir d' ici )
la source
@JsonRawValue
@JsonSetter peut vous aider. Voir mon exemple ('data' est censé contenir du JSON non analysé):
la source
En plus de la bonne réponse de Roy Truelove , voici comment injecter le désérialiseur personnalisé en réponse à l'apparition de :
@JsonRawValue
la source
C'est un problème avec vos classes internes. La
Pojo
classe est une classe interne non statique de votre classe de test et Jackson ne peut pas instancier cette classe. Il peut donc sérialiser, mais pas désérialiser.Redéfinissez votre classe comme ceci:
Notez l'ajout de
static
la source
Cette solution simple a fonctionné pour moi:
J'ai donc pu stocker la valeur brute de JSON dans la variable rawJsonValue, puis ce n'était pas un problème de la désérialiser (en tant qu'objet) avec d'autres champs vers JSON et de l'envoyer via mon REST. L'utilisation de @JsonRawValue ne m'a pas aidé car le JSON stocké était désérialisé en tant que chaîne, pas en tant qu'objet, et ce n'était pas ce que je voulais.
la source
Cela fonctionne même dans une entité JPA:
Idéalement, l'ObjectMapper et même JsonFactory sont issus du contexte et sont configurés de manière à gérer correctement votre JSON (standard ou avec des valeurs non standard comme les floats 'Infinity' par exemple).
la source
JsonNode.toString()
documentationMethod that will produce developer-readable representation of the node; which may <b>or may not</b> be as valid JSON.
Donc, c'est en fait une mise en œuvre très risquée.JsonNode.asText()
interne et générera Infinity et d'autres valeurs JSON non standard.Voici un exemple de travail complet de la façon d'utiliser les modules Jackson pour faire
@JsonRawValue
fonctionner dans les deux sens (sérialisation et désérialisation):Ensuite, vous pouvez enregistrer le module après avoir créé le
ObjectMapper
:la source
org.codehaus.jackson
package sans m'en rendre compte. Assurez-vous que toutes vos importations proviennent decom.fasterxml.jackson
.J'ai eu exactement le même problème. J'ai trouvé la solution dans cet article: analyser l'arborescence JSON en classe simple en utilisant Jackson ou ses alternatives
Découvrez la dernière réponse. En définissant un setter personnalisé pour la propriété qui prend un JsonNode comme paramètre et appelle la méthode toString sur le jsonNode pour définir la propriété String, tout fonctionne.
la source
L'utilisation d'un objet fonctionne très bien dans les deux sens ... Cette méthode a un peu de surcharge pour désérialiser la valeur brute en deux fois.
RawHello.java
RawJsonValue.java
la source
J'ai eu un problème similaire, mais en utilisant une liste avec beaucoup d'itens JSON (
List<String>
).J'ai géré la sérialisation en utilisant l'
@JsonRawValue
annotation. Mais pour la désérialisation, j'ai dû créer un désérialiseur personnalisé basé sur la suggestion de Roy.Ci-dessous vous pouvez voir mon désérialiseur "Liste".
la source