J'utilise:
Foo f = o.mapTo(Foo.class, Map.of("bar_star","barStar","my_bool","myBool");
Disons que nous avons une classe:
var o = new JsonObject(`{"bar_star":"yes","my_bool":true}`);
et ensuite nous avons un JsonObject comme ceci: p>
class Foo { public String barStar; public boolean myBool; }
y a-t-il un mécanisme intégré pour mapper le JsonObject aux champs correspondants dans la classe? Je pense à une sorte d'instance de carte, comme ceci:
import io.vertx.core.json.JsonObject;
pour que vous passiez une instance de carte, et cela indiquerait à JsonObject comment mapper les champs? Peut en quelque sorte montrer un exemple de la façon de faire cela? Je demande spécifiquement comment mapper les champs avant de désérialiser une classe.
3 Réponses :
La documentation de Jackson databind décrit comment convertir une charge utile String
en POJO
, Map
vers POJO
et autres. Jetez un œil aux méthodes readValue
et convertValue
de ObjectMapper
.
EDIT
Vous n'avez qu'un seul problème avec la convention de dénomination. Les propriétés POJO
ne correspondent pas à JSON
. Vous devez utiliser la stratégie de dénomination SNAKE_CASE
ou l'annotation JsonProperty
sur la propriété:
@JsonProperty("bar_star") public String barStar;
Le code ci-dessus est imprimé:
Node: {"bar_star":"yes","my_bool":true} Convert node to Foo: Foo{barStar='yes', myBool=true} Deserialise JSON to Foo: Foo{barStar='yes', myBool=true}
JsonProperty
vous pouvez utiliser comme ci-dessous:
String json = "{\"bar_star\":\"yes\",\"my_bool\":true}"; ObjectMapper mapper = new ObjectMapper(); mapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE); JsonNode node = mapper.readTree(json); System.out.println("Node: " + node); System.out.println("Convert node to Foo: " + mapper.convertValue(node, Foo.class)); System.out.println("Deserialise JSON to Foo: " + mapper.readValue(json, Foo.class));
pouvez-vous s'il vous plaît montrer un exemple de la façon de procéder? Cela pourrait faire gagner du temps à de nombreuses personnes.
Sur la page liée, jetez un œil à la section Use it
( github .com / FasterXML / jackson-databind # use-it ) il contient exactement ce dont vous avez besoin.
@MrCholo jetez un œil à ma réponse et votez si cela vous convient. Comme mentionné, vous voudrez peut-être jeter un œil au référentiel.
J'ai créé une petite application qui illustre cela.
Pour donner un sens à tout, il est probablement préférable de jeter un œil à l'ensemble de la base de code.
Trouvez-le sur: https://github.com/thokari/epages-app-kickstart
Je poste du code, comme cela est généralement requis sur stackoverflow.
Voici la classe de base Model
et une classe qui l'étend:
package de.thokari.epages.app.model; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.util.Base64; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import io.vertx.core.MultiMap; import io.vertx.core.logging.Logger; import io.vertx.core.logging.LoggerFactory; public class InstallationRequest extends Model { private static final Logger LOG = LoggerFactory.getLogger(InstallationRequest.class); @JsonProperty("code") public String code; @JsonProperty("api_url") public String apiUrl; @JsonProperty("access_token_url") public String accessTokenUrl; @JsonProperty("return_url") public String returnUrl; @JsonProperty("token_path") public String tokenPath; @JsonProperty("signature") public String signature; @JsonCreator public InstallationRequest( @JsonProperty("code") String code, @JsonProperty("api_url") String apiUrl, @JsonProperty("access_token_url") String accessTokenUrl, @JsonProperty("return_url") String returnUrl, @JsonProperty("signature") String signature) { this.code = validate("code", code); this.apiUrl = validate("api_url", apiUrl); this.accessTokenUrl = validate("access_token_url", accessTokenUrl); this.returnUrl = validate("return_url", returnUrl); this.signature = validate("signature", signature); try { this.tokenPath = accessTokenUrl.substring(apiUrl.length()); } catch (Exception e) { throw new IllegalArgumentException("access_token_url must contain api_url"); } } public static InstallationRequest fromMultiMap(MultiMap source) { return new InstallationRequest( source.get("code"), // source.get("api_url"), // source.get("access_token_url"), // source.get("return_url"), // source.get("signature")); } public static InstallationRequest fromCallbackUrl(String callbackUrl) { String query = callbackUrl.split("\\?")[1]; String[] parameters = query.split("&"); String code = parameters[0].split("=")[1]; String accessTokenUrl = parameters[1].split("=")[1]; String urlEncodedSignature = parameters[2].split("=")[1]; String signature = null; try { signature = URLDecoder.decode(urlEncodedSignature, "utf-8"); } catch (UnsupportedEncodingException e) { LOG.error("Something went wrong because of a programming error"); } // TODO why is this missing?! String apiUrl = accessTokenUrl.substring(0, accessTokenUrl.indexOf("/token")); return new InstallationRequest(code, apiUrl, accessTokenUrl, "not_needed", signature); } public Boolean hasValidSignature(String secret) { String algorithm = "HmacSHA256"; String encoding = "utf-8"; Mac mac; try { mac = Mac.getInstance(algorithm); mac.init(new SecretKeySpec(secret.getBytes(encoding), algorithm)); } catch (NoSuchAlgorithmException | InvalidKeyException | UnsupportedEncodingException e) { LOG.error("Signature validation failed because of programming error", e); return false; } byte[] rawSignature = mac.doFinal((this.code + ":" + this.accessTokenUrl).getBytes()); String signature = Base64.getEncoder().encodeToString(rawSignature); return this.signature.equals(signature); } }
package de.thokari.epages.app.model; import io.vertx.core.json.Json; import io.vertx.core.json.JsonObject; public abstract class Model { public static <T extends Model> T fromJsonObject(JsonObject source, Class<T> clazz) { return Json.decodeValue(source.encode(), clazz); } public JsonObject toJsonObject() { return new JsonObject(Json.encode(this)); } protected static <T> T validate(final String key, final T value) { if (null == value) { throw new IllegalArgumentException(key + " must not be null"); } else { return (T) value; } } public String toString() { return Json.encode(this); } }
Vert.x a une méthode mapTo
(voir ici ). C'est plus efficace que les solutions proposées d'encodage et de décodage à nouveau quand vous avez déjà un JsonObject
.
Dans les coulisses, Jackson est utilisé pour le mappage, vous pouvez donc simplement utiliser @JsonProperty ("...")
pour remplacer le mappage des propriétés.
Votre exemple serait regardez comme suit:
class Foo { @JsonProperty("bar_start") public String barStar; @JsonProperty("my_bool") public boolean myBool; } JsonObject obj = new JsonObject(`{"bar_star":"yes","my_bool":true}`); Foo foo = obj.mapTo(Foo.class);
Double possible de Meilleur moyen de mapper json à un objet Java a>