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>