{ vendors: [ { vendor: { id: 367, name: "Kuhn-Pollich", company_id: 1, } }, { vendor: { id: 374, name: "Sawayn-Hermann", company_id: 1, } }] }
J’ai un object Vendor qui peut être correctement désérialisé à partir d’un seul “vendeur” json, mais je veux le désérialiser en un Vendor[]
, je n’arrive pas à comprendre comment faire coopérer Jackson. Des conseils?
Vos données posent problème car vous avez des objects wrapper internes dans votre tableau. Vraisemblablement, votre object Vendor
est conçu pour gérer les id
, les name
, company_id
, mais chacun de ces objects multiples est également encapsulé dans un object avec un seul vendor
propriétés.
Je suppose que vous utilisez le modèle Jackson Data Binding .
Si oui, il y a deux choses à considérer:
Le premier utilise une propriété spéciale de configuration de Jackson. Jackson – depuis 1.9 je crois, cela peut ne pas être disponible si vous utilisez une ancienne version de Jackson – fournit UNWRAP_ROOT_VALUE
. Il est conçu pour les cas où vos résultats sont regroupés dans un object de propriété unique de niveau supérieur que vous souhaitez supprimer.
Alors, jouez avec:
objectMapper.configure(SerializationConfig.Feature.UNWRAP_ROOT_VALUE, true);
Le second utilise des objects wrapper. Même après avoir supprimé l’object wrapper externe, le problème de vos objects Vendor
est toujours lié à un object à propriété unique. Utilisez un wrapper pour contourner ceci:
class VendorWrapper { Vendor vendor; // gettors, settors for vendor if you need them }
De même, au lieu d’utiliser UNWRAP_ROOT_VALUES
, vous pouvez également définir une classe wrapper pour gérer l’object externe. En supposant que vous avez un object Vendor
, VendorWrapper
correct, vous pouvez définir:
class VendorsWrapper { List vendors = new ArrayList (); // gettors, settors for vendors if you need them } // in your deserialization code: ObjectMapper mapper = new ObjectMapper(); JsonNode rootNode = mapper.readValue(jsonInput, VendorsWrapper.class);
L’arborescence des objects de VendorsWrapper est analogue à votre JSON:
VendorsWrapper: vendors: [ VendorWrapper vendor: Vendor, VendorWrapper: vendor: Vendor, ... ]
Enfin, vous pouvez utiliser le modèle d’arborescence de Jackson pour parsingr ceci en JsonNodes
, en JsonNodes
le nœud externe, et pour chaque JsonNode
du ArrayNode
, en appelant:
mapper.readValue(node.get("vendor").getTextValue(), Vendor.class);
Cela peut entraîner moins de code, mais cela ne semble pas moins maladroit que d’utiliser deux wrappers.
Voici une solution brute mais plus déclarative. Je n’ai pas réussi à le réduire à une seule annotation, mais cela semble bien fonctionner. Aussi pas sûr de la performance sur les grands ensembles de données.
Vu ce JSON:
{ "list": [ { "wrapper": { "name": "Jack" } }, { "wrapper": { "name": "Jane" } } ] }
Et ces objects modèles:
public class RootObject { @JsonProperty("list") @JsonDeserialize(contentUsing = SkipWrapperObjectDeserializer.class) @SkipWrapperObject("wrapper") public InnerObject[] innerObjects; }
et
public class InnerObject { @JsonProperty("name") public Ssortingng name; }
Où le voodoo de Jackson est implémenté comme:
@Retention(RetentionPolicy.RUNTIME) @JacksonAnnotation public @interface SkipWrapperObject { Ssortingng value(); }
et
public class SkipWrapperObjectDeserializer extends JsonDeserializer
J’espère que c’est utile à quelqu’un!
@ Pasortingck j’améliorerais un peu votre solution
@Override public Object deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { ObjectNode objectNode = jp.readValueAsTree(); JsonNode wrapped = objectNode.get(wrapperKey); JsonParser parser = node.traverse(); parser.setCodec(jp.getCodec()); Vendor mapped = parser.readValueAs(Vendor.class); return mapped; }
Ça marche plus vite 🙂