web-dev-qa-db-ja.com

Jacksonのみを使用してXMLをJSONに変換する方法は?

サーバーからXMLとして応答を受け取っています。ただし、これをJSON形式で表示する必要があります。

サードパーティのAPIなしで変換する方法はありますか?私はジャクソンを使用しましたが、このためにPOJOを作成する必要があります。

サーバーからの応答は次のとおりです。

<?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

Jackson 2.xを使用する

あなたはジャクソンでそれを行うことができ、そのためにPOJOは必要ありません:

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);

次の依存関係が必要です。

<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>

ドキュメント に記載されているXmlMapperの制限に注意してください:

ツリーモデルは限定された方法でのみサポートされています:具体的には、Java配列とCollections 、ただし、追加情報なしでは配列とオブジェクトを区別できないため、読み取ることはできません。

JSON.orgを使用する

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();

次の依存関係が必要です。

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

ここで答えるには遅すぎることを知っています。しかし、私はこの質問に出くわし、@ Cassioの答えを使用することを考えた新しい人のためにこれを書いています。

XmlMpperを使用してJsonNodeに逆シリアル化する問題は、同じレベルに同じ名前の要素が複数ある場合、前の要素を新しい要素に置き換えることです。そして、データが失われます。通常、これを配列に追加する必要があります。この問題に取り組むために、JsonNodeDeserializerクラスの_handleDuplicateField()メソッドをオーバーライドできます。十分な話。コードを見てみましょう

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);
    }
}

デフォルトのデシリアライザをオーバーライドしているため、XmlMapperにこれを登録して機能させる必要があります。

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

サードパーティのAPIを使用せずにxmlをjsonに変換する方法はありますか?

あなたが実用的であるなら、ありません。

XMLを解析するステップは、Java SEの一部であるAPIを使用して実行できます。ただし、解析されたXML(DOMなど)からJSONに移行するにはJSONサポートライブラリが必要であり、Java SEには含まれていません。

(理論的には、あなたはcould自分でそのようなライブラリを書くことができますが、それを行う意味は何ですか?)


私はジャクソンを使用しましたが、このためにPOJOを作成する必要があります。

@Cassioは、Jacksonを使用すると、POJOを作成せずにこの変換を実行できることを指摘しています。または、Java用の他の(サードパーティ)JSON APIをご覧ください。代替のリストについては、 http://www.json.org を参照してください。単純なものの中には、POJOの定義を必要としないものもあります

3
Stephen C

ジャクソンを使用する

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

cassiomolinステップに従いました。 jackson 2.xライブラリを使用しているときに、以下の例外に直面しました。

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

上記の例外にも直面している場合。問題を修正するには、以下のコードを追加してください。その後、ネームスペースなしで変換されたJSONを表示できます。

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

Tips:名前空間なしでXMLを変換する場合は、jacksonライブラリを使用します。 org.json libsを使用しないでください。このユースケースはサポートしていません。

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