2012-04-07 18 views
0

DBからJava(Android)アプリケーションに取得するJSONの解析に問題があります。私はあなたが私を助けることを願って:Json Gsonのバインディングが機能しない(例外オブジェクト/文字列)

これは私が持っているJSONです:

<br> 
[{<br> 
    "ID" : "1",<br> 
    "name" : "Test name",<br> 
    "type" : "1",<br> 
    "Desc" : "blablabla",<br> 
    "minNum" : "0",<br> 
    "maxNum" : "12",<br> 
    "Num" : "8",<br> 
    "bool1" : "0",<br> 
    "bool2" : "1",<br> 
    "bool3" : "1",<br> 
    "date" : "2012-04-01 23:00:00",<br> 
    "double1" : "39.47208",<br> 
    "doubl2" : "-0.3556063",<br> 
    "someText" : "ajayeah",<br> 
    "number" : "15",<br> 
    "anotherNumber" : "1234"<br> 
}, {"ID" : "2",<br> 
    "name" : "Test name",<br> 
    "type" : "1",<br> 
    "Desc" : "blablabla",<br> 
    "minNum" : "0",<br> 
    "maxNum" : "12",<br> 
    "Num" : "8",<br> 
    "bool1" : "0",<br> 
    "bool2" : "1",<br> 
    "bool3" : "1",<br> 
    "date" : "2012-04-01 23:00:00",<br> 
    "double1" : "39.47208",<br> 
    "doubl2" : "-0.3556063",<br> 
    "someText" : "ajayeah",<br> 
    "number" : "15",<br> 
    "anotherNumber" : "1234"<br> 
}]<br> 

(名前はovbiously私がここに書いたものではありません:P)を

私のようにすべてのことを持っています例えばresponseStringという変数のString(チェック済み、OK)。

私は変換を行うためのすべての方法を試しましたが、常に失敗します。私は、Arrayとして、「「[」」]削除対象としてそれを取得しようとしました(私は達成したが、その後、この行が失敗したもの):

MyClassList MyClas = new Gson().fromJson(responseString, MyClassList.class); 

エラーは次のとおりです。

com.google.gson.JsonSyntaxException: 
java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY 

ブーリアンを使用していて、カレンダータイプ(日付)でGsonライブラリでサポートされていない可能性がありますか?

まあ、私はあなたが私が怒っているので、ここから私を得ることを願っています。

感謝:)


は、カレンダーを使用しないでください、それは私の問題でした。代わりに、あなたは、日付を使用することができ、それは動作します。また、私は理由を知らないが、 "0" | "1"のようなブール値は働かない。 "true" | "false"と同じです。

答えて

1

問題は、配列を配列ではないクラスにデシリアライズしようとしていることです。これは明らかな理由で機能しません。配列の型を知っているので、MyClass []のインスタンスを使ってクラスを取得してください。いつでも作成することができます。交互にここで(すなわちMyClass.classMyClass[].classと同じではありません)MyClass[].class

を渡すあなたがlog4j.propertiesファイルを作成する場合、箱から出して実行します(または、ロガーは、システムアウトに変換する例です。

package com.techtrip.test; 

import java.io.Serializable; 

import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 

import com.google.gson.Gson; 

public class GsonTest { 

    private static Logger logger = LoggerFactory.getLogger(GsonTest.class); 

    static ToSerialize t1 = new ToSerialize("1", "Test 1"); 
    static ToSerialize t2 = new ToSerialize("2", "Test 2"); 

    static ToSerialize target[] = {t1,t2} ; 


    /** 
    * @param args 
    */ 
    public static void main(String[] args) { 
     // TODO Auto-generated method stub 

     Gson gson = new Gson(); 

     String jsonStr = gson.toJson(target); 

     logger.info(String.format("Target As String\n: %s", jsonStr)); 

     // This will work as well --> ToSerialize test[] = gson.fromJson(jsonStr, target.getClass()); 
     ToSerialize test[] = gson.fromJson(jsonStr, ToSerialize[].class); 

     for (ToSerialize deserialized: test){ 
      logger.info(String.format("From JSON\n: %s", deserialized.toString())); 
     } 
    } 

} 

class ToSerialize implements Serializable { 

    /** 
    * 
    */ 
    private static final long serialVersionUID = 1L; 


    private String iD; 
    private String name; 


    public ToSerialize() { 
     // TODO Auto-generated constructor stub 
    } 

    public ToSerialize(String iD, String name) { 
     super(); 
     this.iD = iD; 
     this.name = name; 
    } 

    public String getiD() { 
     return iD; 
    } 
    public void setiD(String iD) { 
     this.iD = iD; 
    } 
    public String getName() { 
     return name; 
    } 
    public void setName(String name) { 
     this.name = name; 
    } 
    @Override 
    public int hashCode() { 
     final int prime = 31; 
     int result = 1; 
     result = prime * result + ((iD == null) ? 0 : iD.hashCode()); 
     result = prime * result + ((name == null) ? 0 : name.hashCode()); 
     return result; 
    } 
    @Override 
    public boolean equals(Object obj) { 
     if (this == obj) 
      return true; 
     if (obj == null) 
      return false; 
     if (getClass() != obj.getClass()) 
      return false; 
     ToSerialize other = (ToSerialize) obj; 
     if (iD == null) { 
      if (other.iD != null) 
       return false; 
     } else if (!iD.equals(other.iD)) 
      return false; 
     if (name == null) { 
      if (other.name != null) 
       return false; 
     } else if (!name.equals(other.name)) 
      return false; 
     return true; 
    } 

    @Override 
    public String toString() { 
     return "ToSerialize [iD=" + iD + ", name=" + name + "]"; 
    } 
} 
+0

私はうまくいきませんでした。私はStringクラスでJsonを受け取ります。これは前に書いた構造体と同じように形成されていますが、これを行うことです: MyClass test [] = gson.fromJson(responseString、MyClass []。class); 動作しません。 最後に私は自分でパーサーを書いています。なぜなら、私はこのように動作するようには見えないからです。 私にはうまくいかなかったが、お返事ありがとうございました。 – Sento

+0

申し訳ありませんが、愚かな電話が私の応答をカット。私の例のようにインラインでやってみて、jsonの文字列を比較しましたか?互換性を制限する可能性があるので、独自のパーサを記述する必要はありません。日付を一時的に削除し、テストとして削除することがあります。 – TechTrip

+0

はい、私はそれにはいっていますが、はい。 Jsonの構造は同じです(ただし、名前は例外ですが、クラスと一致します)。今、私はカレンダーの日付に変更しようとし、すべての奇妙なキャラクター(ú)を取り除くつもりです。私は数分で何が起こったか教えてあげよう。 – Sento

0

更新:私は次のコメントをコメントに追加したいと思っていましたが、長すぎます。 BEGIN_OBJECTは{、BEGIN_ARRAYは[です。

次のように起動するかのように、パーサはあなたのJSON文字列を処理しているいくつかの理由

"[[{\"ID\"

javascriptや真には、ときJSONとしてそれを逃れるための試みで、余分な括弧を追加して何かから入ってくるときに、この現象が発生することができますそれはすでにJSON形式です。

私は私が手にそのように設定する私の文字列を変更すると案の定:

Exception in thread "main" com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 3

あなたは、全体の例外を投稿しませんでしたが、私はこのような変換が起こる見てきました。私の恐怖は、パーサが問題ではないときに、あなた自身のJSONパーサを書くということです。 ===================

以下

================オリジナル回答は、私は私の元を変更しましたあなたのJSON文字列をミラーリングする上記のクラスとそれは正常に動作します。私はAndroid上ではないし、おそらくあなたはその環境であなたの問題を引き起こしているものをつかんでいるでしょう。 Dateが問題だった場合、JSON例外として解析不可能な日付が取得されます。これは、"2012-04-01 23:00:00"が失敗してもApr 7, 2012 3:07:40 PMが失敗したセットアップのケースです。ここで

は、それがどのように見えるかです:ここでは

String testString = "[{\"ID\" : \"1\",\"name\" : \"Test name\",\"type\" : \"1\",\"Desc\" : \"blablabla\",\"minNum\" : \"0\",\"maxNum\" : \"12\",\"Num\" : \"8\",\"bool1\" : \"0\",\"bool2\" : \"1\",\"bool3\" : \"1\",\"date\" : \"Apr 7, 2012 3:07:40 PM\",\"double1\" : \"39.47208\",\"doubl2\" : \"-0.3556063\",\"someText\" : \"ajayeah\",\"number\" : \"15\",\"anotherNumber\" : \"1234\"}, {\"ID\" : \"2\",\"name\" : \"Test name\",\"type\" : \"1\",\"Desc\" : \"blablabla\",\"minNum\" : \"0\",\"maxNum\" : \"12\",\"Num\" : \"8\",\"bool1\" : \"0\",\"bool2\" : \"1\",\"bool3\" : \"1\",\"date\" : \"Apr 7, 2012 3:07:40 PM\",\"double1\" : \"39.47208\",\"doubl2\" : \"-0.3556063\",\"someText\" : \"ajayeah\",\"number\" : \"15\",\"anotherNumber\" : \"1234\"}]"; 

    ToSerialize test2[] = gson.fromJson(testString, ToSerialize[].class); 

    for (ToSerialize deserialized : test2) { 
     logger.info(String.format("From JSON\n: %s", 
       deserialized.toString())); 
    } 

が出力されます。

ToSerialize [ID=2, name=Test name, Desc=blablabla, minNum=0, maxNum=12, Num=8, bool1=false, bool2=false, bool3=false, date=Sat Apr 07 15:07:40 CDT 2012, double1=39.47208, doubl2=-0.3556063, someText=ajayeah, number=15, anotherNumber=1234] 

そしてここにクラス定義がある(簡略)私もにやにや笑いのためにブールに投げた)

class ToSerialize { 
    int ID; 
    String name; 
    String Desc; 
    int minNum; 
    int maxNum; 
    int Num; 
    Boolean bool1; 
    boolean bool2; 
    boolean bool3; 
    Date date; 
    double double1; 
    double doubl2; 
    String someText; 
    int number; 
    int anotherNumber; 
    ...... 

これはすべてのアカウントで有効です。

私はGSONの最新バージョン2.1を使用しています。これはあなたのためにうまくいかなければならないどこかのバグかもしれません。

+0

Iveはすでにパーサーを書いていますが、私はこれが私の問題を解決できるかどうかを試してみるつもりです。この問題で他の誰かを助けるかもしれません。あなたの新しい答えをテストしたらすぐにお知らせします。あなたの時間に感謝、非常に感謝:) – Sento

+0

私は(2.1)と同じバージョンを使用して私のプロジェクトにあなたの答えをコピーし、ブーリアンは "true" | "false"ではない "0"として定義する必要がありますが動作します。 "1" 別のことは、日付ではなくカレンダーを使用することです。カレンダーに変更すると例外がスローされます(Jsonの書式を変更しても例外がスローされます)。 私がそれを解決することができれば、私はそれを使用して、自分のパーサーをちょうどの場合に保存します。 私は本当にあなたの助けに感謝します、あなたの時間と努力のために大変ありがとう。 – Sento

+0

ああ、その話題にはあまりにも多くのことがあります。あなたが知っているように、日付は扱いにくいです。問題は、人間が読める形式と、あなたが持っている機械的な時間の間に起こっています。また、あなたの文字列にタイムゾーンや見かけのカレンダーシステムがありません。 (これは、Dateが正しく動作する可能性はありますが、その理由です)日付は非常に複雑です。 Springの世界では、私はJackson JSONパーサーを使用していますが、そのようなことを行うためのDateTimeシリアライザがあります。それは自明ではない。 これはなぜこのような複雑な問題であるかを確認してください。http://wiki.fasterxml.com/JacksonFAQDateHandling – TechTrip

2

最後に、これは私の3番目の回答だとわかっていますが、複数の回答が存在するため、この問題は非常に複雑です。

GSONを使用すると、すぐには動作しません。前に述べた理由から、カレンダーをドロップしてJODAに移動することを強くお勧めします。

あなたが扱っている問題は、日付のシリアライズの問題です。幸運なことに、GSONでは、この目的のためにカスタムシリアライザを登録することができます(独自のパーサーを使用しない別の理由)。あなたはカレンダーのために1つを書くか、すでに書かれたものを探すことができます。

ありがたいことに、これはすでにJODA DateTimesのために行われており、あなた自身の書き込みを希望するあなたのために青いプリントを提供しています。

こちらをご覧ください:https://sites.google.com/site/gson/gson-type-adapters-for-common-classes

を、私はそうと、それを実装:

package com.techtrip.test; 

import java.lang.reflect.Type; 

import org.joda.time.DateTime; 

import com.google.gson.JsonDeserializationContext; 
import com.google.gson.JsonDeserializer; 
import com.google.gson.JsonElement; 
import com.google.gson.JsonParseException; 
import com.google.gson.JsonPrimitive; 
import com.google.gson.JsonSerializationContext; 
import com.google.gson.JsonSerializer; 

public class DateTimeTypeConverter implements JsonSerializer<DateTime>, JsonDeserializer<DateTime> { 
     // No need for an InstanceCreator since DateTime provides a no-args constructor 
     @Override 
     public JsonElement serialize(DateTime src, Type srcType, JsonSerializationContext context) { 
     return new JsonPrimitive(src.toString()); 
     } 
     @Override 
     public DateTime deserialize(JsonElement json, Type type, JsonDeserializationContext context) 
      throws JsonParseException { 
     return new DateTime(json.getAsString()); 
     } 
} 

パーフェクト、今あなたがしなければならないすべてはGSONビルダーに登録し、あなたのための代替としてそれをドロップしていますターゲットクラス(この場合はDateTime.class)。したがって、このクラスを使用して各DateTimeをシリアル化します。本当に華麗です。

public static void main(String[] args) { 
    // TODO Auto-generated method stub 

    GsonBuilder gsonBuilder = new GsonBuilder(); 
    gsonBuilder.registerTypeAdapter(DateTime.class, new DateTimeTypeConverter()); 

    Gson gson = gsonBuilder.create(); 
    String jsonStr = gson.toJson(target); 

    logger.info(String.format("Target As String\n: %s", jsonStr)); 

    // This will work as well --> ToSerialize test[] = 
    // gson.fromJson(jsonStr, target.getClass()); 
    ToSerialize test[] = gson.fromJson(jsonStr, ToSerialize[].class); 

    for (ToSerialize deserialized : test) { 
     logger.info(String.format("From JSON\n: %s", 
       deserialized.toString())); 
    } 

    String testString = "[{\"ID\" : \"1\",\"name\" : \"Test name\",\"type\" : \"1\",\"Desc\" : \"blablabla\",\"minNum\" : \"0\",\"maxNum\" : \"12\",\"Num\" : \"8\",\"bool1\" : \"0\",\"bool2\" : \"1\",\"bool3\" : \"1\",\"date\" : \"2012-04-08T07:50:01.600-05:00\",\"double1\" : \"39.47208\",\"doubl2\" : \"-0.3556063\",\"someText\" : \"ajayeah\",\"number\" : \"15\",\"anotherNumber\" : \"1234\"}, {\"ID\" : \"2\",\"name\" : \"Test name\",\"type\" : \"1\",\"Desc\" : \"blablabla\",\"minNum\" : \"0\",\"maxNum\" : \"12\",\"Num\" : \"8\",\"bool1\" : \"0\",\"bool2\" : \"1\",\"bool3\" : \"1\",\"date\" : \"2012-04-08T07:50:01.600-05:00\",\"double1\" : \"39.47208\",\"doubl2\" : \"-0.3556063\",\"someText\" : \"ajayeah\",\"number\" : \"15\",\"anotherNumber\" : \"1234\"}]"; 

    ToSerialize test2[] = gson.fromJson(testString, ToSerialize[].class); 

    for (ToSerialize deserialized : test2) { 
     logger.info(String.format("From JSON\n: %s", 
       deserialized.toString())); 
    } 
} 

は、いくつかの注意点があり、あなたがこれを理解する必要があります。ここでは

は、それを使用する方法です。まず、2012-04-08T07:50:01.600-05:00のような完全修飾日付時刻書式を含める必要があります。

次に、これらを印刷するためにJODAが提供する多くのもののようなDateTimeFormatterが必要です。必要に応じて、JODAからカレンダーを入手することもできます。

これはJavaのカレンダーでも同様に実行できます。誰かがおそらくすでにそれに取り組んでいるでしょう。がんばろう!

関連する問題