Разбор JSON с помощью Jettison - PullRequest
4 голосов
/ 29 марта 2012

Я пытаюсь проанализировать объект JSON с помощью Jettison. Этот код я использую

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

Я получаю эту ошибку

Исключение в потоке "main" javax.xml.bind.UnmarshalException - со связанным исключением: [javax.xml.bind.UnmarshalException: непредвиденный элемент (uri: "", local: "appUsage"). Ожидаемые элементы (нет)] в com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.handleStreamException (Неизвестно Источник) в com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0 (Неизвестно Источник) в com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal (Неизвестно Источник) на 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.runtime.unmarshaller.UnmarshallingContext.handleEvent (Неизвестно Источник) в com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError (Неизвестно Источник) в com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError (Неизвестно Источник) в com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportUnexpectedChildElement (Неизвестно Источник) в com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext $ DefaultRootLoader.childElement (Неизвестно Источник) в com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext._startElement (Неизвестно Источник) в com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.startElement (Неизвестно Источник) в com.sun.xml.internal.bind.v2.runtime.unmarshaller.InterningXmlVisitor.startElement (Неизвестно Источник) в com.sun.xml.internal.bind.v2.runtime.unmarshaller.StAXStreamConnector.handleStartElement (Неизвестно Источник) в com.sun.xml.internal.bind.v2.runtime.unmarshaller.StAXStreamConnector.bridge (Неизвестно Источник) ... еще 4 причины: javax.xml.bind.UnmarshalException: неожиданный элемент (uri: "", local: "appUsage"). Ожидаемые элементы (нет) ... еще 14

Как решить эту проблему

Ответы [ 3 ]

5 голосов
/ 29 марта 2012

Примечание: Я EclipseLink JAXB (MOXy) и являюсь членом JAXB 2 (JSR-222) экспертная группа.

Если вы в конечном итоге ищете способ взаимодействия с JSON с использованием реализации JAXB (JSR-222), то ниже описано, как это можно сделать с помощью MOXy.Jettison - интересная библиотека, но есть некоторые проблемы, с которыми вы можете столкнуться при ее использовании:

Демо

Используются только стандартные API Java SE.Есть два специфических свойства 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

Я должен был представить этот класс, чтобы удовлетворить ваш вариант использования.Мы могли бы исключить этот класс, если бы ваш 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

Чтобы указать MOXy в качестве вашего JAXB-провайдера, вам нужно добавить файл с именем java.properties со следующей записью в том же пакете, что и классы вашего домена:

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

Выход

Ниже приводится вывод демонстрационного кода:

ANDROID 0
IOS 4

Для получения дополнительной информации

0 голосов
/ 15 июля 2014

Аннотируйте свой класс MiAppUsage с помощью @XmlRootElement (name = "appUsage", namespace = "")

например: - @XmlRootElement (name = "appUsage", namespace = "") открытый класс MiAppUsage {

}

0 голосов
/ 30 марта 2012

Я думаю, что это невозможно сделать с помощью 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 ваш исходный ввод 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);
}

Для получения дополнительной информации о поддержке JAXB StAXON см. Вики-страницу Using JAXB .

...