使用MOXy将JSON字符串解析为“对象”

3
我正在尝试编写一种使用MOXy的方法来美化JSON字符串的方法。所以我想要一个像这样的方法:
public String formatJson(String input) { ... }

我认为最好的方法是将字符串解析为通用对象(类似于SAX文档或类似的对象),然后使用一些格式属性将此对象转换回JSON(这不是问题)。
问题在于,当读取JSON字符串输入时,我没有要解组的类(因为我希望该方法尽可能通用)。
我尝试过这个:
public static String toFormattedJson(final String jsonString) {
    String formatted;
    try {
        JAXBContext jaxbContext = JAXBContextFactory.createContext(new Class[] { JAXBElement.class }, null);
        Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
        unmarshaller.setProperty(MEDIA_TYPE, MediaType.APPLICATION_JSON);
        unmarshaller.setProperty(JSON_INCLUDE_ROOT, true);
        StringReader reader = new StringReader(jsonString);
        Object element = unmarshaller.unmarshal(reader); // Exception is thrown here
        formatted = toFormattedJson(element);
    } catch (final JAXBException e) {
        formatted = jsonString;
    }
    return formatted;
}

但我遇到了这个异常:

javax.xml.bind.UnmarshalException - 带有链接异常: [java.lang.ClassCastException:org.eclipse.persistence.internal.oxm.record.SAXUnmarshallerHandler无法转换为org.eclipse.persistence.internal.oxm.record.UnmarshalRecord]

那么如果我没有特定字符串的任何类,如何将任意JSON字符串读取到Java对象中?

更新: 这是用于将对象格式化为JSON字符串的方法:

private static String toFormattedJson(Object obj) {
    String result;
    try (StringWriter writer = new StringWriter()) {
        final JAXBContext jaxbContext = JAXBContextFactory.createContext(new Class[] { obj.getClass() }, null);
        final Marshaller marshaller = jaxbContext.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.setProperty(JAXBContextProperties.MEDIA_TYPE, MediaType.APPLICATION_JSON);
        marshaller.setProperty(MarshallerProperties.JSON_REDUCE_ANY_ARRAYS, false);
        marshaller.setProperty(MarshallerProperties.JSON_MARSHAL_EMPTY_COLLECTIONS, false);
        marshaller.setProperty(JAXBContextProperties.JSON_WRAPPER_AS_ARRAY_NAME, false);
        marshaller.setProperty(JAXBContextProperties.JSON_INCLUDE_ROOT, true);
        marshaller.marshal(obj, writer);
        writer.flush();
        result = writer.toString();
    } catch (JAXBException | IOException e) {
        result = obj.toString();
    }
    return result;
}

现在,我将使用以下代码(Martin Vojtek)来尝试格式化文本。
String jsonString = "{\"p\" : [ 1, 2, 3]}";

I get:

{
   "p" : "1"
}
1个回答

2
您可以将String指定为解组目标:
public static void main(String[] args) {
        System.out.println(toFormattedJson("[{\"test\":true}, \"ok\", [\"inner\",1]]"));
}

public static String toFormattedJson(final String jsonString) {
    String formatted;
    try {
        JAXBContext jaxbContext = JAXBContextFactory.createContext(new Class[] { JAXBElement.class }, null);
        System.out.println("jaxbContext="+jaxbContext);
        Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
        unmarshaller.setProperty(JAXBContextProperties.MEDIA_TYPE, MediaType.APPLICATION_JSON);
        unmarshaller.setProperty(JAXBContextProperties.JSON_INCLUDE_ROOT, true);
        StringReader reader = new StringReader(jsonString);
        Object element = unmarshaller.unmarshal(new StreamSource(reader), String.class);
        formatted = toFormattedJsonElement(element);
    } catch (final JAXBException e) {
        e.printStackTrace();
        formatted = jsonString;
    }
    return formatted;
}

private static String toFormattedJsonElement(Object element) {
    return "formatted: " + element;
}

代码现在对我来说运行得更好了。但我仍然有一些问题,其中 Integer-Arrays 没有被正确映射。只是为了确保:JAXBConext、JAXBContextFactory 和 Unmarshaller 类应该来自哪个包?javax.xml.bind 还是 org.eclipse.persistenca.jaxb? - Asturio
1
导入 org.eclipse.persistence.jaxb.JAXBContextFactory; 导入 org.eclipse.persistence.jaxb.JAXBContextProperties; 导入 org.eclipse.persistence.oxm.MediaType;导入 javax.xml.bind.JAXBContext; 导入 javax.xml.bind.JAXBElement; 导入 javax.xml.bind.JAXBException; 导入 javax.xml.bind.Unmarshaller; 导入 javax.xml.transform.stream.StreamSource; 导入 java.io.StringReader; - Martin Vojtek
1
我认为将以下字符串"{"p" : [ 1, 2, 3]}"进行反序列化是一个错误,并已经提交了错误报告https://bugs.eclipse.org/bugs/show_bug.cgi?id=460630。另一方面,我不认为使用MOXy来处理这种情况是最好的选择。你应该使用JSON Processing,例如https://jsonp.java.net/download.html。 - Martin Vojtek
JSONP,好的。由于我们正在使用jersey2进行REST服务,并且它使用MOXy作为默认的JSON处理器,所以我认为使用它是一个不错的想法(只使用一个JSON框架)。对于给定的任务,我们仍然在使用jackson。但是我会看一下JSONP。感谢您的建议。 - Asturio
1
最新的 MOXy 2.6.0-M3 在底层使用 JSON-P 作为 Json 解析器/读取器。 - Martin Vojtek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接