如何仅使用Jackson将XML转换为JSON?

时间:2016-09-14 14:35:15

标签: java json xml jackson

我从服务器获得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>

7 个答案:

答案 0 :(得分:20)

使用Jackson 2.x

你可以用Jackson做到这一点,并且不需要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>

请注意documentation中所述的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>

答案 1 :(得分:3)

我知道我来不及回答了。但是我是为那些偶然发现这个问题并想使用@Cassio答案的新人写的。

使用XmlMpper反序列化为JsonNode的问题是,当在同一级别有多个具有相同名称的元素时,它将用新元素替换前一个元素一并最终导致数据丢失。通常,我们必须将此添加到数组中。为了解决这个问题,我们可以重写_handleDuplicateField()类的JsonNodeDeserializer方法。聊够了。让我们看一下代码

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

答案 2 :(得分:2)

  

有没有办法在不使用任何第三方API的情况下将xml转换为json?

如果你是实际的,那就没有了。

解析XML的步骤可以使用属于Java SE的API来执行。但是,从解析的XML(例如DOM)到JSON需要JSON支持库,而Java SE不包含JSON。

(理论上你可以自己编写这样一个库,但这样做有什么意义呢?)

  

我使用了杰克逊,但为此我需要创建POJO。

@Cassio指出杰克逊允许你在不编写POJO的情况下进行翻译。或者,查看Java的其他(第三方)JSON API;请参阅http://www.json.org以获取备选方案列表。一些较简单的不涉及定义POJO

答案 3 :(得分: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();
        }
    }
}

答案 4 :(得分:0)

使用杰克逊

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

答案 5 :(得分:0)

我刚刚遵循了卡西莫林步骤。使用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);

提示: 如果要转换不带名称空间的XML,请使用jackson库。不要去org.json库。它不支持此用例。

答案 6 :(得分:0)

根据 Jackson 的作者,Jackson 2.12 is able to read XML with readTree even with duplicate elements

<块引用>

注意:Jackson 2.12 版允许使用 readTree() 读取重复元素。 (也适用于 java.lang.Object 的名义类型,即所谓的“无类型”绑定)。

所以你可以使用

z = -(a*x +b*y + d)/c