Comment puis-je inclure des premières JSON dans un objet à l'aide de Jackson?
Je suis en train d'essayer d'inclure des premières JSON à l'intérieur d'un objet Java lorsque l'objet est (de)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 affiche la ligne suivante:
{"foo":"one","bar":{"A":false}}
Le JSON est exactement la façon dont je veux que les choses à regarder. Malheureusement, le code ne fonctionne pas avec une exception lors de la tentative de lecture du JSON dans l'objet. Ici est l'exception:
org.codehaus.jackson.carte.JsonMappingException: ne Peut pas désérialiser instance de java.lang.Chaîne de START_OBJECT jeton
à [Source: java.io.StringReader@d70d7a; ligne: 1, colonne: 13] (à travers la chaîne de référence: com.tnal.prism.le cobalt.se rassembler.les tests.Pojo["bar"])
Pourquoi Jackson fonction très bien dans un sens mais ne parviennent pas, quand on va dans une autre direction? Il me semble qu'il devrait être en mesure de prendre ses propres sorties comme entrée. Je sais ce que je suis en train de faire est peu orthodoxe (le conseil général est de créer un objet interne pour bar
qui possède une propriété nommée A
), mais je ne veux pas d'interagir avec du JSON à tous. Mon code est en agissant comme un pass-through " pour ce code, je veux prendre en JSON et de l'envoyer à nouveau, sans toucher à une chose, parce que quand le JSON des changements, je ne veux pas que mon code pour avoir besoin de modifications.
Merci pour les conseils.
EDIT: Fait Pojo une classe statique, ce qui provoquait une erreur différente.
Vous devez vous connecter pour publier un commentaire.
@JsonRawValue est prévu pour la sérialisation de côté, car le sens inverse est un peu plus compliqué à gérer. En effet, il a été ajouté pour permettre l'injection de pré-codées de contenu.
Je suppose qu'il serait possible d'ajouter le support pour la marche arrière, bien que ce serait assez maladroit: le contenu devra être analysée, puis ré-écrit pour en revenir à "raw" à la forme, qui peut ou peut ne pas être le même (puisque caractère citant peuvent différer).
Ceci pour le cas général. Mais peut-être qu'il aurait du sens pour certains sous-ensembles de problèmes.
Mais je pense qu'un travail autour de votre cas serait de spécifier le type comme " java.lang.Objet", puisque cela devrait fonctionner ok: pour la sérialisation, la Chaîne sera de sortie comme il est, et pour la désérialisation, il sera désérialisé comme une Carte. En fait, vous pourriez vouloir séparer les getter/setter si oui; getter serait Chaîne de retour pour la sérialisation (et les besoins de @JsonRawValue); et de définition serait de prendre une Carte ou d'un Objet. Possibilité de ré-encoder une Chaîne si cela fait sens.
Suivantes @StaxMan réponse, j'ai fait les travaux suivants comme un charme:
Et, pour être fidèle à la question initiale, ici, c'est le travail de test:
getJson()
retourne unString
après tout. Si il revient tout juste de laJsonNode
qui a été définie par le poseur, il serait sérialisé en tant désiré, non?toString()
.J'ai été en mesure de le faire avec un custom deserializer (coupé et collé à partir ici)
@JsonRawValue
@JsonSetter peut aider. Voir mon exemple ("data" est censé contenir unparsed JSON):
C'est un problème avec votre intérieur des classes. Le
Pojo
classe est un non-statique à l'intérieur de la classe de votre classe de test, et Jackson ne peut pas instancier cette classe. De sorte qu'il peut sérialiser, mais pas désérialiser.Redéfinir votre classe comme ceci:
Notez l'ajout de
static
Ajoutant à Roy Truelove's grande réponse, c'est la façon d'injecter la coutume deserialiser en réponse à l'apparition de
@JsonRawValue
:Cette solution facile a fonctionné pour moi:
J'ai donc été en mesure de stocker la valeur brute de JSON dans rawJsonValue variable et puis il n'était pas un problème pour désérialiser (comme objet) avec d'autres champs JSON et de les envoyer via mon REPOS. À l'aide de @JsonRawValue ne m'a aidé parce stockées JSON est désérialisé comme une Chaîne de caractères, non pas comme objet, et ce n'était pas ce que je voulais.
Ceci fonctionne même dans une entité JPA:
Idéalement, le ObjectMapper et même JsonFactory sont à partir du contexte et sont configurés de manière à traiter votre JSON correctement (standard ou non-standard des valeurs comme "Infini" chars par exemple).
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 effectivement très risqué de mise en œuvre.JsonNode.asText()
en interne et de sortie de l'Infini et d'autres non-standard JSON valeurs.J'ai eu exactement le même problème.
J'ai trouvé la solution dans ce post :
Parser JSON arbre à la plaine de classe à l'aide de Jackson ou de ses alternatives
Découvrez la dernière réponse.
En définissant une coutume setter de la propriété qui prend un JsonNode comme paramètre, et appelle la méthode toString sur le jsonNode à l'ensemble de la Chaîne de propriété, tout fonctionne.
À l'aide d'un objet fonctionne bien à la fois les moyens... Cette méthode a un peu de surcharge de la désérialisation la valeur brute en deux fois.
RawHello.java
RawJsonValue.java
Voici une exemple de la façon d'utiliser Jackson modules pour rendre
@JsonRawValue
fonctionner dans les deux sens (de la sérialisation et la désérialisation):Ensuite, vous pouvez enregistrer le module après la création de la
ObjectMapper
:org.codehaus.jackson
paquet sans s'en rendre compte. Assurez-vous que tous vos importations viennent de l'com.fasterxml.jackson
.J'ai eu un problème similaire, mais en utilisant une liste avec beaucoup de JSON itens (
List<String>
).J'ai géré la sérialisation à l'aide de la
@JsonRawValue
annotation. Mais pour la désérialisation, j'ai dû créer un personnalisé deserializer basé sur Roy suggestion.Ci-dessous vous pouvez voir ma "Liste" deserializer.