「BEGIN_OBJECTが必要ですが、1行1列目はSTRINGでした」


126

私はこの方法を持っています:

public static Object parseStringToObject(String json) {
    String Object = json;
    Gson gson = new Gson();
    Object objects = gson.fromJson(object, Object.class);
    parseConfigFromObjectToString(object);
    return objects;
}

そして、私はJSONを解析したいと思います:

public static void addObject(String IP, Object addObject) {
    try {
        String json = sendPostRequest("http://" + IP + ":3000/config/add_Object", ConfigJSONParser.parseConfigFromObjectToString(addObject));
        addObject = ConfigJSONParser.parseStringToObject(json);
    } catch (Exception ex) {
        ex.printStackTrace();
    }
}

しかし、私はエラーメッセージを受け取ります:

com.google.gson.JsonSyntaxException:java.lang.IllegalStateException:BEGIN_OBJECTが必要ですが、1行1列目がSTRINGでした


2
投稿リクエストによって返されたJSON文字列を投稿します。
Adrian Leonhard

JSON文字列を投稿
bhspencer

回答:


163

JSON文字列を確認しなくても、エラーメッセージから、クラスのインスタンスに解析するのに適切な構造ではないことがわかります。

Gsonは、JSON文字列がオブジェクトの開き括弧で始まることを期待しています。例えば

{

しかし、あなたがそれに渡した文字列は、開いている引用符で始まります

"

1
そして、メソッドのまさにその名前がその理由を示唆しています。parseStringToObjectは常にJSONで始まるJSONオブジェクトを想定していることを示唆しています{
yshavit 2015

12
'['は、Jsonオブジェクトではなく、Json配列の開始を示します。
bhspencer 2016年

私はそれを知っていました。しかし、それを解析するために何をしなければなりませんか?
Ajay Mistry 2017

@AjayMistry詳細がなければ、何を求めているのか明確ではありません。解析しようとしているJSONの例を使用して、新しい質問に特定の問題を投稿することをお勧めします。
bhspencer 2017

1
親愛なる@bhspencer私はAndroid APKでレトロフィットを使用して、バックエンド{"ip":"192.167.1.15"}からのような単純なjsonを取得Restful EJB web service with jboss EAP 7.1しています。ただし、「BEGIN_OBJECTが予期されていましたが、1行1列目がSTRINGでした」というメッセージが表示されます。助けてください...これは私のWebサービスです:@Stateless @Path( "/ getflashcard")public class GetFlashcard {@Interceptors(Validator.class)@GET @Produces(MediaType.APPLICATION_JSON)public String getFlashcard(){String jsonString = new JSONObject()。put( "ip"、 "192.167.1.15")。toString(); jsonStringを返します。}}
Hosein Aqajani

17

サーバーからの無効なJSONは、常に予期される使用例です。送信中に100万の問題が発生する可能性があります。Gsonは少し注意が必要です。エラー出力によって1つの問題が発生し、キャッチする実際の例外は別のタイプになるためです。

これらすべてを考慮して、クライアント側での適切な修正は

try
{
  gson.fromJSON(ad, Ad.class);
  //...
}
catch (IllegalStateException | JsonSyntaxException exception)
{
  //...

サーバーから受け取ったJSONが間違っている理由を知りたい場合は、例外のcatchブロック内を調べることができます。しかし、それが問題であっても、インターネットから受信しているJSONを修正するのはクライアントの責任ではありません。

いずれにせよ、JSONが不良になったときにどうするかを決めるのはクライアントの責任です。2つの可能性は、JSONを拒否して何もしないことと、再試行することです。

もう一度試す場合は、try / catchブロック内にフラグを設定し、try / catchブロックの外側でそのフラグに応答することを強くお勧めします。ネストされたtry / catchは、Gsonがスタックトレースと例外を一致させずにこの混乱に陥らせた方法と思われます。

つまり、見た目はあまりエレガントではないことは認めますが、

boolean failed = false;

try
{
  gson.fromJSON(ad, Ad.class);
  //...
}
catch (IllegalStateException | JsonSyntaxException exception)
{
  failed = true;
  //...
}

if (failed)
{
  //...

これは、簡単にするためにブール値を使用したビューを取得しているため、追加したいと思います。「現実の世界」では、収集した例外データを個々のtry / catchブロック内に格納した文字列の存在をテストし、トランザクションの履歴を自分で再生して、インテリジェントな決定を行うことができます。再試行するかどうか、および最終的に失敗すると決定したときに有用な出力を送信するかどうか。
ジェシカPennell

5

Retrofit2では、パラメータをそのまま送信する場合は、スカラーを使用する必要があります。

まずこれをあなたのgradleに追加してください:

    compile 'com.squareup.retrofit2:retrofit:2.3.0'
    compile 'com.squareup.retrofit2:converter-gson:2.3.0'
    compile 'com.squareup.retrofit2:converter-scalars:2.3.0'

    public interface ApiInterface {

    String URL_BASE = "http://10.157.102.22/rest/";

    @Headers("Content-Type: application/json")
    @POST("login")
    Call<User> getUser(@Body String body);

}

私のSampleActivity:

   public class SampleActivity extends AppCompatActivity implements Callback<User> {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sample);

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(ApiInterface.URL_BASE)
                .addConverterFactory(ScalarsConverterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        ApiInterface apiInterface = retrofit.create(ApiInterface.class);


        // prepare call in Retrofit 2.0
        try {
            JSONObject paramObject = new JSONObject();
            paramObject.put("email", "sample@gmail.com");
            paramObject.put("pass", "4384984938943");

            Call<User> userCall = apiInterface.getUser(paramObject.toString());
            userCall.enqueue(this);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }


    @Override
    public void onResponse(Call<User> call, Response<User> response) {
    }

    @Override
    public void onFailure(Call<User> call, Throwable t) {
    }
}

参照:[ 改造リクエストの本文に未加工のJSON全体をPOSTする方法は?


3

多分JSON Object正しいですが、受け取った応答は有効なデータではありません。無効を接続したときと同様にWiFi、解析できない奇妙な応答< html>.....< /html>を受け取った可能性GSONがあります。

try..catch..クラッシュを回避するために、この奇妙な応答に対していくつかの操作が必要になる場合があります。


3

解決策を共有するようになりました。notbookを強制終了した後、エラーが発生しました。可能な解決策clean preject


3

DATE / DATETIMEなどのDESERIALIZEDオブジェクトがあることを確認してください。JSONを非シリアル化せずに直接送信すると、この問題が発生する可能性があります。


送信前にシリアル化されましたか?
ratzip 2018

@ratzip申し訳ありませんが、DATE | 日付時刻。JsonObjectをJAVAオブジェクトにマップするときにこの問題に直面していました。
Ravi Wadje 2018

3

私の状況では、1つを除いていくつかの文字列パラメーターで構成される「モデル」がありますbyte[]。それはバイト配列です。いくつかのコードスニペット:

String response = args[0].toString();
Gson gson = new Gson();
BaseModel responseModel = gson.fromJson(response, BaseModel.class);

上記の最後の行は、

java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column

トリガーされます。SOを検索して、JsonObject Adapterに変換BaseModelしたり、JsonObject に変換したりするための何らかの形式が必要であることに気付きました。モデル内とモデル内で混在させるStringbyte[]、事態が複雑になります。どうやら、Gson本当に状況を好きではありません。

私は最終的にフォーマットに変換されるAdapterことを確認して作ることにbyte[]なりBase64ます。これが私のAdapterクラスです:

public class ByteArrayToBase64Adapter implements JsonSerializer<byte[]>, JsonDeserializer<byte[]> {

    @Override
    public byte[] deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        return Base64.decode(json.getAsString(), Base64.NO_WRAP);
    }

    @Override
    public JsonElement serialize(byte[] src, Type typeOfSrc, JsonSerializationContext context) {
        return new JsonPrimitive(Base64.encodeToString(src, Base64.NO_WRAP));
    }
}

JSONObjectをモデルに変換するために、以下を使用しました。

Gson customGson = new GsonBuilder().registerTypeHierarchyAdapter(byte[].class, new ByteArrayToBase64Adapter()).create();
BaseModel responseModel = customGson.fromJson(response, BaseModel.class);

同様に、モデルをJSONObjectに変換するために、以下を使用しました。

Gson customGson = new GsonBuilder().registerTypeHierarchyAdapter(byte[].class, new ByteArrayToBase64Adapter()).create();
String responseJSon = customGson.toJson(response);

コードが行っていることは、基本的にはclass/object、JSONObjectへの変換/ JSONObjectへの変換中に遭遇byte[]するAdapterたびに、意図した(この場合はクラス)をプッシュすることです。



0

私の場合、私はJSONオブジェクトを

{"data": ""、 "メッセージ": "出席が正常に保存されました.. !!!"、 "status": "成功"}

次のように変更することで解決しました

{"data":{}、 "message": "出席が正常に保存されました.. !!!"、 "status": "success"}

ここでデータはサブJsonObjectであり、{ではなく ""から始まる必要があります


0

json形式と変数に問題がない場合は、データベースクエリを確認してください。データが正しくdbに保存されている場合でも、実際の問題がそこにある可能性があります...クエリを再確認して、もう一度試してください。


0

最初にGson()を使用してオブジェクトをJsonに変換することを忘れないでください

  val fromUserJson = Gson().toJson(notificationRequest.fromUser)

次に、この素​​晴らしいライブラリを使用して、オブジェクトに簡単に戻すことができます

      val fromUser = Gson().fromJson(fromUserJson, User::class.java)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.