4

我正在尝试使用 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;
    }

我收到此错误

线程“主”javax.xml.bind.UnmarshalException 中的异常 - 带有链接异常:[javax.xml.bind.UnmarshalException:意外元素(uri:“”,本地:“appUsage”)。预期的元素是(无)] 在 com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl 的 com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.handleStreamException(未知来源)。 com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(未知来源)在 com.json.UnmarshalDemo.jsonParser(UnmarshalDemo.java:56) 在 com.json.UnmarshalDemo .main(UnmarshalDemo.java:33) 引起:javax.xml.bind.UnmarshalException:意外元素(uri:“”,本地:“appUsage”)。com.sun.xml.internal.bind.v2 中的预期元素是(无)。v2.runtime.unmarshaller.StAXStreamConnector.handleStartElement(Unknown Source) at com.sun.xml.internal.bind.v2.runtime.unmarshaller.StAXStreamConnector.bridge(Unknown Source) ... 4 更多原因:javax.xml.bind .UnmarshalException:意外元素(uri:“”,本地:“appUsage”)。预期的元素是(无)... 14 更多

如何解决这个问题

4

3 回答 3

5

注意: 我是EclipseLink JAXB (MOXy)负责人,也是JAXB 2 (JSR-222)专家组的成员。

如果您最终正在寻找一种使用 JAXB (JSR-222) 实现与 JSON 交互的方法,那么以下是如何使用 MOXy 来完成的。Jettison 是一个有趣的库,但使用它会遇到一些问题:

演示

仅使用标准 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);
        }
    }

}

我不得不介绍这个类来满足你的用例。如果你的 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;

}

MiApp使用

package forum9924567;

import javax.xml.bind.annotation.*;

@XmlAccessorType(XmlAccessType.FIELD)
public class MiAppUsage {

    String appName;
    int totalUsers;

}

jaxb.properties

要将 MOXy 指定为您的 JAXB 提供程序,您需要在与域类相同的包中添加一个名为java.properties以下条目的文件:

javax.xml.bind.context.factory = org.eclipse.persistence.jaxb.JAXBContextFactory

输出

以下是运行演示代码的输出:

ANDROID 0
IOS 4

了解更多信息

于 2012-03-29T18:30:42.850 回答
0

我认为 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));
}

这打印:

ANDROID: 0
IOS: 4

带有 JAXB 注释的模型类是这样的:

import javax.xml.bind.annotation.*;

@XmlRootElement(name = "appUsage")
@XmlAccessorType(XmlAccessType.FIELD)
public class MiAppUsage {
  String appName;
  int totalUsers;
}

作为 Jettison的替代方案,您可以使用StAXONJsonXMLMapper轻松解析原始 JSON 输入,它适用于任何 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);
}

有关 StAXON 的 JAXB 支持的更多信息,请参阅使用 JAXB wiki 页面。

于 2012-03-30T13:18:43.013 回答
0

使用 @XmlRootElement(name = "appUsage", namespace="") 注释您的 MiAppUsage 类

例如:- @XmlRootElement(name = "appUsage", namespace="") 公共类 MiAppUsage {

}

于 2014-07-15T13:46:14.450 回答