web-dev-qa-db-fra.com

Comment convertir XML en JSON en utilisant uniquement Jackson?

Je reçois une réponse du serveur en XML. Mais je dois l'afficher au format JSON.

Existe-t-il un moyen de le convertir sans aucune API tierce? J'ai utilisé Jackson, mais pour cela, je dois créer POJO.

La réponse du serveur est comme ceci:

<?xml version='1.0'?>
<errors><error><status>400</status><message>The field 'quantity' is invalid.</message><details><invalid_reason>The quantity specified is greater than the quantity of the product that is available to ship.</invalid_reason><available_quantity>0</available_quantity><order_product_id>12525</order_product_id></details></error></errors>
11
sudar

Utiliser Jackson 2.x

Vous pouvez le faire avec Jackson et aucun POJO n'est requis pour cela:

String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
             "<errors>\n" +
             "  <error>\n" +
             "    <status>400</status>\n" +
             "    <message>The field 'quantity' is invalid.</message>\n" +
             "    <details>\n" +
             "      <invalid_reason>The quantity specified is greater than the quantity of the product that is available to ship.</invalid_reason>\n" +
             "      <available_quantity>0</available_quantity>\n" +
             "      <order_product_id>12525</order_product_id>\n" +
             "    </details>\n" +
             "  </error>\n" +
             "</errors>";

XmlMapper xmlMapper = new XmlMapper();
JsonNode node = xmlMapper.readTree(xml.getBytes());

ObjectMapper jsonMapper = new ObjectMapper();
String json = jsonMapper.writeValueAsString(node);

Les dépendances suivantes sont requises:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.8.2</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.8.2</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>2.8.2</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
    <version>2.8.2</version>
</dependency>

Soyez conscient des limitations de XmlMapper indiquées dans documentation :

Le modèle d'arbre n'est pris en charge que de façon limitée: spécifiquement, Java et Collections peuvent être écrits , mais ne peut pas être lu, car il n'est pas possible de distinguer les tableaux et les objets sans informations supplémentaires.

Utilisation de JSON.org

Vous pouvez également le faire avec JSON.org:

String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
             "<errors>\n" +
             "  <error>\n" +
             "    <status>400</status>\n" +
             "    <message>The field 'quantity' is invalid.</message>\n" +
             "    <details>\n" +
             "      <invalid_reason>The quantity specified is greater than the quantity of the product that is available to ship.</invalid_reason>\n" +
             "      <available_quantity>0</available_quantity>\n" +
             "      <order_product_id>12525</order_product_id>\n" +
             "    </details>\n" +
             "  </error>\n" +
             "</errors>";

String json = XML.toJSONObject(xml).toString();

La dépendance suivante est requise:

<dependency>
    <groupId>org.json</groupId>
    <artifactId>json</artifactId>
    <version>20160810</version>
</dependency>
22
cassiomolin

Je sais que je suis trop tard pour obtenir une réponse ici. Mais j'écris ceci pour les nouveaux gars qui sont tombés sur cette question et qui pensent utiliser la réponse de @ Cassio.

Le problème de l'utilisation de XmlMpper pour désérialiser un JsonNode est que, lorsqu'il y a plusieurs éléments avec le même nom au même niveau, il remplacera le précédent par le nouveau et se retrouver avec une perte de données. Habituellement, nous devons l'ajouter à un tableau. Pour résoudre ce problème, nous pouvons remplacer la méthode _handleDuplicateField() de la classe JsonNodeDeserializer. Assez parlé. Voyons le code

public class DuplicateToArrayJsonNodeDeserializer extends JsonNodeDeserializer {

    @Override
    protected void _handleDuplicateField(JsonParser p, DeserializationContext ctxt, 
        JsonNodeFactory nodeFactory,String fieldName, ObjectNode objectNode,
        JsonNode oldValue, JsonNode newValue) throws JsonProcessingException {
        ArrayNode node;
        if(oldValue instanceof ArrayNode){
            node = (ArrayNode) oldValue;
            node.add(newValue);
        } else {
            node = nodeFactory.arrayNode();
            node.add(oldValue);
            node.add(newValue);
        }
        objectNode.set(fieldName, node);
    }
}

Puisque nous avons remplacé le désérialiseur par défaut, nous devons également l'enregistrer dans le XmlMapper pour le faire fonctionner.

XmlMapper xmlMapper = new XmlMapper();
xmlMapper.registerModule(new SimpleModule().addDeserializer(
    JsonNode.class, 
    new DuplicateToArrayJsonNodeDeserializer()
));
JsonNode node = xmlMapper.readTree(payLoad);
6
Tino M Thomas

Existe-t-il un moyen de convertir xml en json sans utiliser d'API tierce?

Si vous êtes pratique, non, il n'y en a pas.

L'étape d'analyse du XML peut être effectuée à l'aide d'API qui font partie de Java SE. Cependant, passer du XML analysé (par exemple un DOM) à JSON nécessite une bibliothèque de prise en charge JSON, et Java SE n'en inclut pas.

(En théorie, vous pourriez écrire vous-même une telle bibliothèque, mais à quoi ça sert?)


J'ai utilisé Jackson, mais pour cela, je dois créer POJO.

@Cassio souligne que Jackson vous permet de faire cette traduction sans écrire de POJO. Vous pouvez également consulter d'autres API JSON (tierces) pour Java; voir http://www.json.org pour une liste d'alternatives. Certains des plus simples n'impliquent pas la définition de POJO

3
Stephen C

Utiliser jackson

import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import Java.io.IOException;

public class JsonUtil {

    private static XmlMapper XML_MAPPER = new XmlMapper();
    private static ObjectMapper JSON_MAPPER = new ObjectMapper();

    public static ObjectMapper getJsonMapper(){
        return JSON_MAPPER;
    }

    public static XmlMapper getXmlMapper(){
        return XML_MAPPER;
    }

    public static String xmlToJson(String xml){
        try {
            return getJsonMapper().writeValueAsString(getXmlMapper().readTree(xml));
        } catch (IOException e) {
            e.printStackTrace();
            return "";
        }
    }
}
1
prodigy4440

Je viens de suivre cassiomoline étapes. J'ai rencontré une exception ci-dessous lors de l'utilisation des bibliothèques jackson 2.x.

Cannot create XMLStreamReader or XMLEventReader from a org.codehaus.stax2.io.Stax2ByteArraySource

Si vous faites également face à l'exception ci-dessus. Ajoutez le code ci-dessous pour résoudre le problème. Ensuite, vous pouvez voir le JSON converti sans l'espace de noms.

JacksonXmlModule module = new JacksonXmlModule();
module.setDefaultUseWrapper(false);
XmlMapper xmlMapper = new XmlMapper(module);

Conseils: Si vous souhaitez convertir le XML sans l'espace de noms, utilisez la bibliothèque jackson. N'allez pas pour les bibliothèques org.json. Il ne prend pas en charge ce cas d'utilisation.

0
package com.src.test;

import Java.io.IOException;
import Java.io.InputStream;
import Java.net.URL;

import org.Apache.commons.io.IOUtils;

import net.sf.json.JSON;
import net.sf.json.xml.XMLSerializer;

public class JSONConverter {
    private static URL url = null;
    private static InputStream input = null;

    public static void main(String args[]) throws IOException {
        try {
            url = JSONConverter.class.getClassLoader().getResource("sampleXmlFilePath.xml");
            input = url.openStream();
            String xmlData = IOUtils.toString(input);

            XMLSerializer xmlSerializer = new XMLSerializer();
            JSON json = xmlSerializer.read(xmlData);
            System.out.println("JSON format : " + json);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            input.close();
        }
    }
}
0
Ganesh