java 使用 Jettison 解析 JSON
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9924567/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
JSON parsing using Jettison
提问by prem
I am trying to parse JSON object using Jettison. This the code I'm using
我正在尝试使用 Jettison 解析 JSON 对象。这是我正在使用的代码
String s ="{\"appUsage\":[{\"appName\":\"ANDROID\",\"totalUsers\":\"0\"},{\"appName\":\"IOS\",\"totalUsers\":\"4\"}]}";
JSONObject obj = new JSONObject(s);
ArrayList<MiAppUsage> l1 = (ArrayList<MiAppUsage>) jsonParser(ArrayList.class, obj);
public static Object jsonParser(Class c, JSONObject obj)
throws JSONException, XMLStreamException, JAXBException {
JAXBContext jc = JAXBContext.newInstance(c);
Configuration config = new Configuration();
MappedNamespaceConvention con = new MappedNamespaceConvention(config);
XMLStreamReader xmlStreamReader = new MappedXMLStreamReader(obj, con);
Unmarshaller unmarshaller = jc.createUnmarshaller();
ArrayList<MiAppUsage>customer = (ArrayList<MiAppUsage>) unmarshaller.unmarshal(xmlStreamReader);
return customer;
}
I'm getting this error
我收到这个错误
Exception in thread "main" javax.xml.bind.UnmarshalException - with linked exception: [javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"appUsage"). Expected elements are (none)] at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.handleStreamException(Unknown Source) at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(Unknown Source) at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(Unknown Source) at com.json.UnmarshalDemo.jsonParser(UnmarshalDemo.java:56) at com.json.UnmarshalDemo.main(UnmarshalDemo.java:33) Caused by: javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"appUsage"). Expected elements are (none) at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(Unknown Source) at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Unknown Source) at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Unknown Source) at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportUnexpectedChildElement(Unknown Source) at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext$DefaultRootLoader.childElement(Unknown Source) at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext._startElement(Unknown Source) at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.startElement(Unknown Source) at com.sun.xml.internal.bind.v2.runtime.unmarshaller.InterningXmlVisitor.startElement(Unknown Source) at com.sun.xml.internal.bind.v2.runtime.unmarshaller.StAXStreamConnector.handleStartElement(Unknown Source) at com.sun.xml.internal.bind.v2.runtime.unmarshaller.StAXStreamConnector.bridge(Unknown Source) ... 4 more Caused by: javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"appUsage"). Expected elements are (none) ... 14 more
v2.runtime.unmarshaller.StAXStreamConnector.handleStartElement(Unknown Source) at com.sun.xml.internal.bind.v2.runtime.unmarshaller.StAXStreamConnector.bridge(Unknown Source) ... 4 more 引起:javax.xml.bind .UnmarshalException:意外元素(uri:“”,本地:“appUsage”)。预期元素是(无)... 14 更多
How to resolve this problem
如何解决这个问题
回答by bdoughan
Note:I'm the EclipseLink JAXB (MOXy)lead and a member of the JAXB 2 (JSR-222)expert group.
注意:我是EclipseLink JAXB (MOXy) 的负责人和JAXB 2 (JSR-222)专家组的成员。
If you are ultimately looking for a way to interact with JSON using a JAXB (JSR-222) implementation, then the following is how it can be done using MOXy. Jettison is an interesting library but there are some issue you will encounter using it:
如果您最终正在寻找一种使用 JAXB (JSR-222) 实现与 JSON 交互的方法,那么以下是使用 MOXy 实现的方法。Jettison 是一个有趣的库,但在使用它时你会遇到一些问题:
Demo
演示
Only the standard Java SE APIs are used. There are two MOXy specific properties that need to be set on the Unmarshaller
: "eclipselink.media-type"
to specify "application/json"
, and "eclipselink.json.include-root"
to indicate that there is no root node.
仅使用标准 Java SE API。有两个 MOXy 特定属性需要在Unmarshaller
: "eclipselink.media-type"
指定"application/json"
和"eclipselink.json.include-root"
指示没有根节点上设置。
package forum9924567;
import java.io.StringReader;
import java.util.ArrayList;
import javax.xml.bind.*;
import javax.xml.transform.stream.StreamSource;
public class Demo {
private static final String s ="{\"appUsage\":[{\"appName\":\"ANDROID\",\"totalUsers\":\"0\"},{\"appName\":\"IOS\",\"totalUsers\":\"4\"}]}";
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Root.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
unmarshaller.setProperty("eclipselink.media-type", "application/json");
unmarshaller.setProperty("eclipselink.json.include-root", false);
StreamSource json = new StreamSource(new StringReader(s));
Root root = unmarshaller.unmarshal(json, Root.class).getValue();
ArrayList<MiAppUsage> customer = root.appUsage;
for(MiAppUsage miAppUsage : customer) {
System.out.print(miAppUsage.appName);
System.out.print(' ');
System.out.println(miAppUsage.totalUsers);
}
}
}
Root
根
I had to introduce this class to meet your use case. We could eliminate this class if your JSON looked like: [{"appName":"ANDROID","totalUsers":"0"},{"appName":"IOS","totalUsers":"4"}]
.
我不得不介绍这个类来满足您的用例。我们可以消除这一类,如果你的JSON看起来像: [{"appName":"ANDROID","totalUsers":"0"},{"appName":"IOS","totalUsers":"4"}]
。
package forum9924567;
import java.util.ArrayList;
import javax.xml.bind.annotation.*;
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {
ArrayList<MiAppUsage> appUsage;
}
MiAppUsage
应用程序使用
package forum9924567;
import javax.xml.bind.annotation.*;
@XmlAccessorType(XmlAccessType.FIELD)
public class MiAppUsage {
String appName;
int totalUsers;
}
jaxb.properties
jaxb.properties
To specify MOXy as your JAXB provider you need to add a file called java.properties
with the following entry in the same package as your domain classes:
要将 MOXy 指定为您的 JAXB 提供程序,您需要java.properties
在与域类相同的包中添加一个使用以下条目调用的文件:
javax.xml.bind.context.factory = org.eclipse.persistence.jaxb.JAXBContextFactory
Output
输出
The following is the output from running the demo code:
以下是运行演示代码的输出:
ANDROID 0
IOS 4
For More Information
想要查询更多的信息
回答by chris
I think this cannot be done with Jettison. Seems like the JSONObject
does not like the root element having an array as its value. If it's an option, you may change your input into a JSON array, which can be parsed with Jettison:
我认为这不能用 Jettison 来完成。似乎JSONObject
不喜欢具有数组作为其值的根元素。如果这是一个选项,您可以将输入更改为 JSON 数组,可以使用 Jettison 进行解析:
public static void main(String[] args) throws Exception {
String s ="[{\"appUsage\":{\"appName\":\"ANDROID\",\"totalUsers\":\"0\"}},{\"appUsage\":{\"appName\":\"IOS\",\"totalUsers\":\"4\"}}]";
JSONArray arr = new JSONArray(s);
List<MiAppUsage> list = unmarshal(MiAppUsage.class, arr);
for(MiAppUsage miAppUsage : list) {
System.out.println(miAppUsage.appName + ": " + miAppUsage.totalUsers);
}
}
public static <T> List<T> unmarshal(Class<T> cls, JSONArray arr) throws JSONException, XMLStreamException, JAXBException {
List<T> list = new ArrayList<T>();
for (int i = 0; i < arr.length(); i++) {
list.add(unmarshal(cls, arr.getJSONObject(i)));
}
return list;
}
public static <T> T unmarshal(Class<T> cls, JSONObject obj) throws JSONException, XMLStreamException, JAXBException {
JAXBContext jc = JAXBContext.newInstance(cls);
Configuration config = new Configuration();
MappedNamespaceConvention con = new MappedNamespaceConvention(config);
XMLStreamReader xmlStreamReader = new MappedXMLStreamReader(obj, con);
Unmarshaller unmarshaller = jc.createUnmarshaller();
return cls.cast(unmarshaller.unmarshal(xmlStreamReader));
}
This prints:
这打印:
ANDROID: 0
IOS: 4
The JAXB-annotated model class is like this:
JAXB 注释的模型类是这样的:
import javax.xml.bind.annotation.*;
@XmlRootElement(name = "appUsage")
@XmlAccessorType(XmlAccessType.FIELD)
public class MiAppUsage {
String appName;
int totalUsers;
}
As an alternative to Jettison, your original JSON input can be easily parsed with StAXON's JsonXMLMapper
, which works with any JAXB implementation:
作为替代抛弃,你原来的JSON输入,可方便地与解析StAXON的JsonXMLMapper
,这与任何JAXB实现原理:
String s ="{\"appUsage\":[{\"appName\":\"ANDROID\",\"totalUsers\":\"0\"},{\"appName\":\"IOS\",\"totalUsers\":\"4\"}]}";
JsonXMLMapper<MiAppUsage> mapper = new JsonXMLMapper<MiAppUsage>(MiAppUsage.class);
List<MiAppUsage> list = mapper.readArray(new StringReader(s));
for(MiAppUsage miAppUsage : list) {
System.out.println(miAppUsage.appName + ": " + miAppUsage.totalUsers);
}
For more information on StAXON's JAXB support, refer to the Using JAXBwiki page.
有关 StAXON 的 JAXB 支持的更多信息,请参阅Using JAXBwiki 页面。
回答by Varun
Annotate your class MiAppUsage with @XmlRootElement(name = "appUsage", namespace="")
用 @XmlRootElement(name = "appUsage", namespace="") 注释你的类 MiAppUsage
eg:- @XmlRootElement(name = "appUsage", namespace="") public class MiAppUsage {
例如:- @XmlRootElement(name = "appUsage", namespace="") 公共类 MiAppUsage {
}
}