8

Gson を使用してアプリケーションの状態を JSON として保存し、それをfromJsonを使用して読み取るコードをいくつか継承しました。

Gson gson = createGson();
gson.fromJson(objString, myClass);

保存されるフィールドの 1 つがLocationです。残念ながら、保存された場所の mExtras に mClassLoader が含まれているため、保存されたデータの解析が失敗することが非常にまれであり、Gson ライブラリは次のエラーで ClassLoader の作成に失敗します。

RuntimeException: 引数なしで保護された java.lang.ClassLoader() を呼び出せませんでした

ClassLoader が私の Location のエクストラに含まれている理由と、JSON 表現で終了する必要があるかどうかを知っている人はいますか?

Location オブジェクトの主要なフィールド (経度、緯度、高度、時間、精度など) を個別に保存するだけでこれを修正できると思いますが、可能であれば Location オブジェクトを保存することをお勧めします。

フィールドを除外するために使用できるExclusionStrategyオブジェクトがあることを確認しましたが、それを使用して自分の Location 内からエクストラを除外できるかどうか、または使用する必要があるかどうかはわかりませんでした...

参考までに、これが私の Location オブジェクトの JSON データです (経度と緯度は非表示に変更されています)。

{
    <snip>
    "lastKnownLocation": {
        "mResults": [
            0,
            0
        ],
        "mProvider": "gps",
        "mExtras": {
            "mParcelledData": {
                "mOwnObject": 1,
                "mObject": 5525040
            },
            "mClassLoader": {
                "packages": {}
            },
            "mMap": {},
            "mHasFds": false,
            "mFdsKnown": true,
            "mAllowFds": true
        },
        "mDistance": 0,
        "mTime": 1354658984849,
        "mAltitude": 5.199999809265137,
        "mLongitude": -122.4376,
        "mLon2": 0,
        "mLon1": 0,
        "mLatitude": 37.7577,
        "mLat1": 0,
        "mLat2": 0,
        "mInitialBearing": 0,
        "mHasSpeed": true,
        "mHasBearing": false,
        "mHasAltitude": true,
        "mHasAccuracy": true,
        "mAccuracy": 16,
        "mSpeed": 0,
        "mBearing": 0
    },
    <snip>
}

コードがクラッシュしない場合の mExtras の内容の例を次に示します。

"mExtras": {
    "mParcelledData": {
        "mOwnsNativeParcelObject": true,
        "mNativePtr": 1544474480
    },
    "mHasFds": false,
    "mFdsKnown": true,
    "mAllowFds": true
}
4

3 に答える 3

23

Location問題は、システム提供のクラス ( ) を JSONに直接変換しようとしていることです。そして、ご覧のとおり、内部状態/ Java 固有のものをシリアライズする際に問題が発生します。JSON は、情報を渡す半汎用的な方法を意図しています。

@Exposeクラスではないため、注釈を簡単に使用することはできません。jassistLocationを使用して実行時にそれらを追加するため、またはかなり広範なプロセスを介してソースコードを変更する必要があります(参照:http ://ayoubelabbassi.blogspot.com/2011/01/how-to-add-annotations-at-runtime- to.html )

クラスを見るとLocation、カスタムの Gson シリアライザーとデシリアライザーを作成するだけで完了です。実際に関心があるのは GPS データであり、クラス自体の内部ではありません。ゲッターを使用して、シリアライザーで必要な情報を含む JSON を作成するだけです。次に、デシリアライザーで新しいインスタンスを作成Locationし、パブリック セッターを使用して提供された JSON からの情報を入力します。

class LocationSerializer implements JsonSerializer<Location>
{
    public JsonElement serialize(Location t, Type type, 
                                 JsonSerializationContext jsc)
    {
        JsonObject jo = new JsonObject();
        jo.addProperty("mProvider", t.getProvider());
        jo.addProperty("mAccuracy", t.getAccuracy());
        // etc for all the publicly available getters
        // for the information you're interested in
        // ...
        return jo;
    }

}

class LocationDeserializer implements JsonDeserializer<Location>
{
    public Location deserialize(JsonElement je, Type type, 
                                JsonDeserializationContext jdc)
                           throws JsonParseException
    {
        JsonObject jo = je.getAsJsonObject();
        Location l = new Location(jo.getAsJsonPrimitive("mProvider").getAsString());
        l.setAccuracy(jo.getAsJsonPrimitive("mAccuracy").getAsFloat());
        // etc, getting and setting all the data
        return l;
    }
}

GsonBuilderコードで、クラスを使用して登録します。

...
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Location.class, new LocationDeserializer());
gsonBuilder.registerTypeAdapter(Location.class, new LocationSerializer());
Gson gson = gsonBuilder.create(); 
...

それはかなりそれを世話するはずです。

于 2012-12-21T22:19:33.630 に答える
2

GSON をモデル化するカスタム オブジェクトを作成し、オブジェクトごとにコンテンツ オブジェクトを解析し、フィールドごとにフィールドを解析することを検討してください。

何かのようなもの

JSONObject lastKnownLocation = obj.getJSONObject("lastKnownLocation");
JSONArray mResults = lastKnownLocation.getJSONArray("mResults");

etc...
MyGSON mg=new MyGSON(lastKnownLocation, mResults etc....);

したがって、解析を完全に制御し、重要な mExtra 部分に try\catch ブロックを追加して、ブロックを除外したり、必要に応じて例外を簡単に管理したりできます。

于 2012-12-23T01:27:22.877 に答える