web-dev-qa-db-fra.com

Mappage élégant de POJO au JsonObject de vertx.io?

Je travaille actuellement sur une application vertx.io et je voulais utiliser l’API mongo fournie pour le stockage des données. J'ai actuellement une abstraction plutôt maladroite au-dessus des classes JsonObject de stock, où toutes les méthodes get et set sont remplacées par des éléments tels que:

this.backingObject.get(KEY_FOR_THIS_PROPERTY);

C'est bien beau pour le moment, mais ça ne va pas très bien. cela semble également sale, en particulier lorsque vous utilisez des tableaux ou des objets imbriqués. Par exemple, si je veux pouvoir remplir des champs uniquement lorsque les données réelles sont connues, je dois vérifier si le tableau existe et s'il ne le crée pas et le stocke dans l'objet. Ensuite, je peux ajouter un élément à la liste. Par exemple:

if (this.backingObject.getJsonArray(KEY_LIST) == null) {
    this.backingObject.put(KEY_LIST, new JsonArray());
}
this.backingObject.getJsonArray(KEY_LIST).add(p.getBackingObject());

J'ai réfléchi aux solutions potentielles, mais je n'aime pas particulièrement l'une d'entre elles. À savoir, j pourrait utiliser Gson ou une bibliothèque similaire avec un support d'annotation pour gérer le chargement de l'objet dans le but de manipuler les données dans mon code, puis d'utiliser la fonction serialize et unserialize de Gson et Vertx pour la conversion. entre les formats (vertx to load data -> json string -> gson to parse json into pojos -> make changes -> serialize to json string -> parse with vertx and save) mais c'est un flux de travail vraiment grossier et inefficace. Je pourrais aussi probablement trouver une sorte de wrapper abstrait qui étend/implémente la bibliothèque vertx json mais transmet toutes les fonctionnalités à gson, mais cela semble aussi beaucoup de travail.

Existe-t-il un moyen efficace d'obtenir une sérialisation plus conviviale et maintenable à l'aide de vertx?

16
grdaneault

Je viens de soumettre un correctif à Vert.x qui définit deux nouvelles fonctions pratiques pour la conversion entre les instances d'objet Json et JsonObject sans l'inefficacité de passer par une représentation chaîne JSON intermédiaire. Ce sera dans la version 3.4.

// Create a JsonObject from the fields of a Java object.
// Faster than calling `new JsonObject(Json.encode(obj))`.
public static JsonObject mapFrom(Object obj)

// Instantiate a Java object from a JsonObject.
// Faster than calling `Json.decodeValue(Json.encode(jsonObject), type)`.
public <T> T mapTo(Class<T> type)

En interne, cela utilise ObjectMapper#convertValue(...), voir la réponse de Tim Putnam pour les mises en garde relatives à cette approche. Le code est ici .

24
Luke Hutchison

Vous ne savez pas si je vous ai bien compris, mais on dirait que vous essayez de trouver un moyen simple de convertir des POJO en JsonObject?

Nous avons donc beaucoup de pojos que nous envoyons sur la EventBus comme JsonObjects

J'ai trouvé le moyen le plus simple d'utiliser la classe vert.xJson qui contient de nombreuses méthodes d'assistance à convertir en/à partir de JsonStrings

JsonObject jsonObject = new JsonObject(Json.encode(myPojo));

Parfois, vous avez besoin d’ajouter des (dés) sérialiseurs personnalisés, mais nous nous en tenons toujours à Jackson - c’est ce que Vert.x utilise pour qu’ils fonctionnent immédiatement. 

En réalité, nous fournissons une interface semblable à celle-ci:

public JsonObjectSerializable {
    public JsonObject toJson();
}

Et tous nos pojos qui doivent être envoyés sur la EventBus doivent implémenter cette interface. 

Alors notre code d'envoi EventBus ressemble à (simplifié):

public <T extends JsonObjectSerializable> Response<T> dispatch(T eventPayload);

De plus, comme nous ne faisons généralement pas de tests unitaires sur les pojos, l'ajout de cette interface encourage les développeurs à tester leurs conversions à l'aide d'unités. 

J'espère que cela t'aides, 

Volonté

8
Will

Je crois que les fonctions ObjectMapper.convertValue(..) de Jackson ne sont pas converties via String et que Vert.x utilise Jackson pour gérer JsonObject de toute façon. 

JsonObject a juste une carte sous-jacente représentant les valeurs, accessible via JsonObject.getMap(), et un sérialiseur/désérialiseur de Jackson sur l'instance publique ObjectMapper dans io.vertx.core.json.Json.

Pour basculer entre JsonObject et un modèle de données exprimé en Pojos sérialisable avec Jackson, vous pouvez effectuer les opérations suivantes:

JsonObject myVertxMsg = ... MyPojo pojo = Json.mapper.convertValue ( myVertxMsg.getMap(), MyPojo.class );

J'imagine que c'est plus efficace que de passer par une chaîne (mais c'est juste une hypothèse), et je déteste l'idée de modifier la classe de données simplement pour l'adapter à l'environnement. Cela dépend donc du contexte, de la forme par rapport à la performance.

Pour convertir Pojo en JsonObject, convertissez-le en carte avec Jackson puis utilisez le constructeur sur JsonObject:

JsonObject myobj = new JsonObject ( Json.mapper.convertValue ( pojo, Map.class ));

  • Si vous avez impliqué des objets JsonObjects ou JsonArray imbriqués dans votre définition, ils seront instanciés en tant que cartes et listes par défaut. JsonObject les réemballera en interne lorsque vous accéderez à des champs spécifiant ces types (par exemple, avec getJsonArray (..).

  • Étant donné que JsonObject est une forme libre et que vous convertissez en un type statique, vous pouvez obtenir une exception UnrecognizedPropertyException non désirée. Il peut être utile de créer votre propre ObjectMapper, d’ajouter les vertx JsonObjectSerializer et JsonArraySerializer, puis d’apporter des modifications de configuration appropriées (comme DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES dans Jackson).

7
Tim Putnam

Je pense que l'utilisation de Gson comme vous l'avez décrit est la meilleure solution possible à l'heure actuelle.

Bien que je convienne que si une couche de protocole était incluse dans Vert.x, ce serait effectivement le premier prix, l'utilisation de Gson permet de garder les internes de votre serveur bien organisés et ne constitue probablement pas le goulot d'étranglement des performances.

Quand et seulement quand cette stratégie devient le goulot d'étranglement des performances, avez-vous atteint le point de concevoir une meilleure solution? Tout ce qui précède est une optimisation prématurée.

Mes deux centimes.

0
Daniel Gerson

Essaye ça:

io.vertx.core.json.Json.mapper.convertValue(json.getMap(), cls)
0
fengbugou