3

我正在尝试使用 Json Reader 解析 .json 文件以将记录插入到我的数据库中,但我在读取文件时遇到问题。

我特意用 try/catch 子句打开了解析/读取器的方法,这样我就可以看到错误是从哪里来的。

这是 json Parser/Reader 类:

package cybertech.productions.servicehelpers;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;

import android.content.Context;

import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;

public class JsonParser {

    public void readCardJsonStream1(String cardSet, CarddbAdapter yugiohDB,
            Context context) throws IOException {

        URL test = new URL(cardSet);
        InputStream in = new BufferedInputStream(test.openStream());

        JsonReader reader = new JsonReader(new InputStreamReader(in,
                "ISO-8859-1"));

        String s, s1, s2, levelstr, rankstr, atkstr, defstr, setnumstr, cardpasstr;

        int numTotalElements = 0;
        int elementsParsed = 0;

        reader.beginObject();
        s = reader.nextName();

        reader.beginObject();
        while (reader.hasNext()) {

            s = reader.nextName();
            if (s.equalsIgnoreCase("p")) { // cards

                reader.beginObject();
                while (reader.hasNext()) {
                    s1 = reader.nextName();
                    if (s1.equalsIgnoreCase("o")) { // card
                        YugiohCard c;
                        reader.beginArray();
                        while (reader.hasNext()) {

                            reader.beginObject();
                            c = new YugiohCard();
                            while (reader.hasNext()) {
                                s2 = reader.nextName();
                                if (s2.equalsIgnoreCase("a")) { // name
                                    c.name = reader.nextString();
                                } else if (s2.equalsIgnoreCase("b")) { // type
                                    c.type = reader.nextString();
                                } else if (s2.equalsIgnoreCase("c")) { // attribute_type
                                    c.attributeType = reader.nextString();
                                } else if (s2.equalsIgnoreCase("d")) { // summon_requirements
                                    c.summonRequirements = reader.nextString();
                                } else if (s2.equalsIgnoreCase("e")) { // description
                                    c.description = reader.nextString();
                                } else if (s2.equalsIgnoreCase("f")) { // spell
                                                                        // speed
                                    c.spellSpeed = reader.nextString();

                                } else if (s2.equalsIgnoreCase("g")) { // level_stars
                                    levelstr = reader.nextString();
                                    c.levelStars = Integer.parseInt(levelstr);
                                } else if (s2.equalsIgnoreCase("h")) { // rank_stars
                                    rankstr = reader.nextString();
                                    c.rankStars = Integer.parseInt(rankstr);
                                } else if (s2.equalsIgnoreCase("i")) { // atk_points
                                    atkstr = reader.nextString();
                                    c.atk_stat = Integer.parseInt(atkstr);
                                } else if (s2.equalsIgnoreCase("j")) { // def_points
                                    defstr = reader.nextString();
                                    c.def_stat = Integer.parseInt(defstr);
                                } else if (s2.equalsIgnoreCase("n")) { // set
                                                                        // initials
                                    c.setinit = reader.nextString();
                                } else if (s2.equalsIgnoreCase("k")) { // set_number
                                    setnumstr = reader.nextString();
                                    c.setNumber = Integer.parseInt(setnumstr);
                                } else if (s2.equalsIgnoreCase("l")) { // card_number_pass
                                    cardpasstr = reader.nextString();
                                    c.cardnumberPass = Integer
                                            .parseInt(cardpasstr);
                                }
                            }
                            yugiohDB.createDBCard(c);
                            reader.endObject();
                        }
                        reader.endArray();
                    }
                }
                reader.endObject();
            }
            if (s.equalsIgnoreCase("w")) { // num_cards
                numTotalElements = reader.nextInt();
            }
        }
        reader.endObject();
        reader.close();
    }
}

这是我的 Json 文件:

{
    "t": {
        "p": {
            "o": [
                {
                    "a": "Elemental HERO Absolute Zero",
                    "b": "Monster/Fusion/Effect",
                    "c": "WATER",
                    "d": "1 'HERO' monster + 1 WATER monster",
                    "e": "Blows up your field, sucks for you",
                    "f": "NULL",
                    "g": "8",
                    "h": "0",
                    "i": "2500",
                    "j": "2000",
                    "n": "YG04",
                    "k": "001",
                    "l": "40854197"
                },
                {
                    "a": "Elemental HERO Air Neos",
                    "b": "Monster/Fusion/Effect",
                    "c": "WIND",
                    "d": "Hummingbird + Neos",
                    "e": "Returns to extra at end phase",
                    "f": "NULL",
                    "g": "7",
                    "h": "0",
                    "i": "2500",
                    "j": "2000",
                    "n": "STON",
                    "k": "034",
                    "l": "11502550"
                },
                {
                    "a": "Cyber Jar",
                    "b": "Monster/Effect",
                    "c": "DARK",
                    "d": "NULL",
                    "e": "destroys all monsters on the field",
                    "f": "NULL",
                    "g": "3",
                    "h": "0",
                    "i": "900",
                    "j": "900",
                    "n": "MRL",
                    "k": "077",
                    "l": "34124316"
                },
                {
                    "a": "Wind-Up Carrier Zenmaity",
                    "b": "MACHINE/Xyz/Effect",
                    "c": "WATER",
                    "d": "2 Level 3 monsters",
                    "e": "Special summon a wind-up from your hand or deck.",
                    "f": "NULL",
                    "g": "0",
                    "h": "3",
                    "i": "1500",
                    "j": "1500",
                    "n": "ORCS",
                    "k": "044",
                    "l": "81122844"
                },
                {
                    "a": "BRAIN CONTROL",
                    "b": "Spell",
                    "c": "Spell",
                    "d": "NULL",
                    "e": "Pay 800 Life Points to target 1 face-up monster your opponent controls; take control of that target until the End Phase.",
                    "f": "Normal",
                    "g": "0",
                    "h": "0",
                    "i": "0",
                    "j": "0",
                    "n": "LCYW",
                    "k": "074",
                    "l": "87910978"
                },
                {
                    "a": "Ring of Destruction",
                    "b": "Trap",
                    "c": "Trap",
                    "d": "NULL",
                    "e": "Target 1 face-up monster on the field; destroy that target, and if you do, inflict damage to both players equal to that target's ATK.",
                    "f": "Normal",
                    "g": "0",
                    "h": "0",
                    "i": "0",
                    "j": "0",
                    "n": "YG04",
                    "k": "001",
                    "l": "40854197"
                }
            ]
        },
        "v": "2/3/2013"
    }
}

这是我创建的一种方法,用于判断 json 文件在我的网站上的位置:

public void CreateYUGIsets() throws MalformedURLException, IOException{
        yugiohDB.dropDB();
        JsonParser parser = new JsonParser();
        String cardSetList = "https://sites.google.com/site/yugiohlibrary/patches/test.json";
        parser.readCardJsonStream1(cardSetList, yugiohDB, this);
    }

这是我也遇到的 Logcat 错误:

05-15 22:48:49.362: E/AndroidRuntime(476): FATAL EXCEPTION: main
05-15 22:48:49.362: E/AndroidRuntime(476): java.lang.RuntimeException: Unable to start activity ComponentInfo{cybertech.productions.yugiohlibrary/cybertech.productions.yugiohlibrary.LoadingScreen}: java.lang.IllegalStateException: Expected a name but was STRING
05-15 22:48:49.362: E/AndroidRuntime(476):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1647)
05-15 22:48:49.362: E/AndroidRuntime(476):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1663)
05-15 22:48:49.362: E/AndroidRuntime(476):  at android.app.ActivityThread.access$1500(ActivityThread.java:117)
05-15 22:48:49.362: E/AndroidRuntime(476):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931)
05-15 22:48:49.362: E/AndroidRuntime(476):  at android.os.Handler.dispatchMessage(Handler.java:99)
05-15 22:48:49.362: E/AndroidRuntime(476):  at android.os.Looper.loop(Looper.java:123)
05-15 22:48:49.362: E/AndroidRuntime(476):  at android.app.ActivityThread.main(ActivityThread.java:3683)
05-15 22:48:49.362: E/AndroidRuntime(476):  at java.lang.reflect.Method.invokeNative(Native Method)
05-15 22:48:49.362: E/AndroidRuntime(476):  at java.lang.reflect.Method.invoke(Method.java:507)
05-15 22:48:49.362: E/AndroidRuntime(476):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
05-15 22:48:49.362: E/AndroidRuntime(476):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
05-15 22:48:49.362: E/AndroidRuntime(476):  at dalvik.system.NativeStart.main(Native Method)
05-15 22:48:49.362: E/AndroidRuntime(476): Caused by: java.lang.IllegalStateException: Expected a name but was STRING
05-15 22:48:49.362: E/AndroidRuntime(476):  at com.google.gson.stream.JsonReader.nextName(JsonReader.java:444)
05-15 22:48:49.362: E/AndroidRuntime(476):  at cybertech.productions.servicehelpers.JsonParser.readCardJsonStream1(JsonParser.java:36)
05-15 22:48:49.362: E/AndroidRuntime(476):  at cybertech.productions.yugiohlibrary.LoadingScreen.CreateYUGIsets(LoadingScreen.java:107)
05-15 22:48:49.362: E/AndroidRuntime(476):  at cybertech.productions.yugiohlibrary.LoadingScreen.onCreate(LoadingScreen.java:41)
05-15 22:48:49.362: E/AndroidRuntime(476):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
05-15 22:48:49.362: E/AndroidRuntime(476):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1611)
05-15 22:48:49.362: E/AndroidRuntime(476):  ... 11 more

对于 logcat 中的这一特定行:cybertech.productions.servicehelpers.JsonParser.readCardJsonStream1(JsonParser.java:36) 05-15 22:48:49.362: E/AndroidRuntime(476)

JsonParser 类中的第 36 行是:s = reader.nextName();

该行就在第一个 while() 循环开始之后。

任何帮助,将不胜感激。

4

1 回答 1

4

您选择了最繁琐的方法来解析 JSON 文件。您正在使用的库 (Gson) 提供了更简单的方法来处理输入。这是一个仍然进行手动解析的示例:

// Your JSON data here
final String json = "";

// Get the array element corresponding to t->p->o, in the data
final JsonElement rootElem = new JsonParser().parse(json);
final JsonArray jsonArr = rootElem.getAsJsonObject()
        .getAsJsonObject("t").getAsJsonObject("p").getAsJsonArray("o");

// Iterate through the JSON array, extracting out card info as we go
final List<Yugioh> cards = new ArrayList<Yugioh>(jsonArr.size());
for (final JsonElement objElem : jsonArr) {
    final JsonObject jsonObj = objElem.getAsJsonObject();
    final Yugioh card = new Yugioh();

    card.setName(jsonObj.get("a").getAsString());
    card.setType(jsonObj.get("b").getAsString());
    card.setAttributeType(jsonObj.get("c").getAsString());
    card.setSummonRequirements(jsonObj.get("d").getAsString());
    card.setDescription(jsonObj.get("e").getAsString());
    card.setSpellSpeed(jsonObj.get("f").getAsString());
    card.setLevelStars(Integer.parseInt(jsonObj.get("g").getAsString()));
    card.setRankStars(Integer.parseInt(jsonObj.get("h").getAsString()));
    card.setAtkStat(Integer.parseInt(jsonObj.get("i").getAsString()));
    card.setDefStat(Integer.parseInt(jsonObj.get("j").getAsString()));
    card.setNumber(Integer.parseInt(jsonObj.get("k").getAsString()));
    card.setCardNumberPass(Integer.parseInt(jsonObj.get("l")
            .getAsString()));
    card.setInit(jsonObj.get("n").getAsString());

    System.out.println(card);
    cards.add(card);
}

请注意代码的可读性更高。我冒昧地说明了 getter/setter 的正确使用,并修正了一些变量名。您可以进一步缩短上面的示例,方法是在您的映射器类中指明您要从中复制的 JSON 属性的序列化名称。举个例子,使用这个映射器类:

class Yugioh implements Serializable {
    private static final long serialVersionUID = -8125568453376399843L;

    @SerializedName("a")
    private String name;

    @SerializedName("b")
    private String type;

    @SerializedName("c")
    private String attributeType;

    @SerializedName("d")
    private String summonRequirements;

    @SerializedName("e")
    private String description;

    @SerializedName("f")
    private String spellSpeed;

    @SerializedName("g")
    private Integer levelStars;

    @SerializedName("h")
    private Integer rankStars;

    @SerializedName("i")
    private Integer atkStat;

    @SerializedName("j")
    private Integer defStat;

    @SerializedName("k")
    private Integer number;

    @SerializedName("l")
    private Integer cardNumberPass;

    @SerializedName("n")
    private String init;

    public Yugioh() {
        super();
    }

    // Getters/Setters here

    @Override
    public String toString() {
        return String.format("Card %s", getName());
    }
}

您可以显着缩短反序列化代码:

// Your JSON data here
final String json = "";

// Deserialize JSON into a bunch of objects
final JsonElement rootElem = new JsonParser().parse(json);
final JsonArray jsonArr = rootElem.getAsJsonObject()
        .getAsJsonObject("t").getAsJsonObject("p").getAsJsonArray("o");
final List<Yugioh> cards = new Gson().fromJson(jsonArr,
        new TypeToken<List<Yugioh>>() {
        }.getType());

System.out.println(cards);

死的简单。请务必阅读Gson 用户指南- 它提供了大量有关使用该库的有用信息。

于 2013-05-16T03:39:57.467 回答