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:""、local:"appUsage")。予想される要素は、com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.handleStreamException(Unknown Source) の (none)] です。 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:""、local:"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:""、local:"appUsage")。期待される要素は (なし) ... 14 以上

この問題を解決する方法

4

3 に答える 3

5

注: 私はEclipseLink JAXB (MOXy)のリーダーであり、JAXB 2 (JSR-222)エキスパート グループのメンバーです。

最終的に JAXB (JSR-222) 実装を使用して JSON とやり取りする方法を探している場合は、MOXy を使用してそれを行う方法を次に示します。Jettison は興味深いライブラリですが、使用するといくつかの問題が発生します。

デモ

標準の Java SE API のみが使用されます。に設定する必要がある MOXy 固有のプロパティが 2 つあり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の代わりに、元の JSON 入力は、任意の JAXB 実装で動作するStAXONを使用して簡単に解析できます。JsonXMLMapper

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 サポートの詳細については、Using JAXB wiki ページを参照してください。

于 2012-03-30T13:18:43.013 に答える
0

クラス MiAppUsage に @XmlRootElement(name = "appUsage", namespace="") で注釈を付けます

例:- @XmlRootElement(name = "appUsage", namespace="") public class MiAppUsage {

}

于 2014-07-15T13:46:14.450 に答える