"คาดหวัง BEGIN_OBJECT แต่เป็น STRING ที่บรรทัด 1 คอลัมน์ 1"


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 แต่เป็น STRING ที่บรรทัด 1 คอลัมน์ 1


2
โพสต์สตริง JSON ที่ส่งคืนตามคำขอโพสต์ของคุณ
Adrian Leonhard

โพสต์สตริง JSON ของคุณ
bhspencer

คำตอบ:


163

แม้ว่าจะไม่เห็นสตริง JSON ของคุณ แต่คุณสามารถบอกได้จากข้อความแสดงข้อผิดพลาดว่ามันไม่ใช่โครงสร้างที่ถูกต้องที่จะแยกวิเคราะห์เป็นอินสแตนซ์ของคลาสของคุณ

Gson คาดว่าสตริง JSON ของคุณจะเริ่มต้นด้วยวงเล็บปีกกาเปิดวัตถุ เช่น

{

แต่สตริงที่คุณส่งผ่านไปเริ่มต้นด้วยเครื่องหมายคำพูดเปิด

"

1
และชื่อของวิธีการแสดงให้เห็นว่าทำไม parseStringToObjectแสดงให้เห็นว่ามันคาดหวังออบเจ็กต์ JSON ซึ่งขึ้นต้นด้วย{เสมอ
yshavit

12
"[" จะระบุจุดเริ่มต้นของ Json Array ไม่ใช่วัตถุ Json
bhspencer

ฉันรู้ว่า .. แต่เราต้องทำอย่างไรเพื่อแยกวิเคราะห์ ??
Ajay Mistry

@AjayMistry ไม่ชัดเจนว่าคุณกำลังถามอะไรโดยไม่มีรายละเอียดเพิ่มเติม ฉันขอแนะนำให้โพสต์ปัญหาเฉพาะของคุณในคำถามใหม่พร้อมตัวอย่าง JSON ที่คุณพยายามแยกวิเคราะห์
bhspencer

1
เรียน @bhspencer ฉันใช้ชุดติดตั้งเพิ่มเติมใน android apk เพื่อรับ json แบบง่ายๆ{"ip":"192.167.1.15"}จากRestful EJB web service with jboss EAP 7.1ในแบ็กเอนด์ อย่างไรก็ตามฉันได้รับ“ BEGIN_OBJECT ที่คาดไว้ แต่เป็น STRING ที่บรรทัด 1 คอลัมน์ 1” โปรดช่วยฉันด้วย ... นี่คือบริการบนเว็บของฉัน: @Stateless @Path ("/ getflashcard") คลาสสาธารณะ GetFlashcard {@Interceptors (Validator.class) @GET @Produces (MediaType.APPLICATION_JSON) String สาธารณะ getFlashcard () {String jsonString = new JSONObject (). put ("ip", "192.167.1.15"). toString (); ส่งคืน jsonString; }}
Hosein Aqajani

17

JSON ที่ไม่ถูกต้องจากเซิร์ฟเวอร์ควรเป็นกรณีการใช้งานที่คาดไว้เสมอ สิ่งต่างๆนับล้านอาจผิดพลาดระหว่างการส่งสัญญาณ Gson ค่อนข้างยุ่งยากเพราะผลลัพธ์ข้อผิดพลาดจะทำให้คุณมีปัญหาหนึ่งข้อและข้อยกเว้นจริงที่คุณจับได้จะเป็นประเภทอื่น

ด้วยเหตุนี้การแก้ไขที่เหมาะสมในฝั่งไคลเอ็นต์คือ

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

หากคุณต้องการทราบว่าเหตุใด JSON ที่คุณได้รับจากเซิร์ฟเวอร์จึงไม่ถูกต้องคุณสามารถดูข้อยกเว้นใน catch block ได้ แม้ว่าจะเป็นปัญหาของคุณ แต่ลูกค้าก็ไม่ต้องรับผิดชอบในการแก้ไข JSON ที่ได้รับจากอินเทอร์เน็ต

ไม่ว่าจะด้วยวิธีใดลูกค้าเป็นความรับผิดชอบในการตัดสินใจว่าจะทำอย่างไรเมื่อได้รับ JSON ที่ไม่ดี ความเป็นไปได้สองประการคือการปฏิเสธ JSON และไม่ทำอะไรเลยแล้วลองอีกครั้ง

หากคุณกำลังจะลองอีกครั้งขอแนะนำอย่างยิ่งให้ตั้งค่าสถานะภายในบล็อก try / catch จากนั้นตอบสนองต่อแฟล็กนั้นนอกบล็อก try / catch การลอง / จับที่ซ้อนกันเป็นไปได้ว่า Gson ทำให้เรายุ่งเหยิงกับการติดตามสแต็กและข้อยกเว้นที่ไม่ตรงกันได้อย่างไร

กล่าวอีกนัยหนึ่งแม้ว่าฉันจะยอมรับว่ามันดูไม่สวยหรู แต่ฉันก็อยากแนะนำ

boolean failed = false;

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

if (failed)
{
  //...

ฉันต้องการเพิ่มเนื่องจากนี่เป็นการรับมุมมองที่ฉันใช้บูลีนเพื่อความเรียบง่าย ใน "โลกแห่งความเป็นจริง" คุณอาจต้องการทดสอบการมีอยู่ของสตริงที่คุณเก็บข้อมูลข้อยกเว้นที่คุณรวบรวมไว้ในบล็อก try / catch แต่ละรายการโดยจะเล่นซ้ำประวัติของธุรกรรมกับตัวคุณเองเพื่อให้คุณสามารถตัดสินใจได้อย่างชาญฉลาด ไม่ว่าจะลองใหม่และส่งผลลัพธ์ที่เป็นประโยชน์เมื่อคุณตัดสินใจล้มเหลวในที่สุด
Jessica Pennell

5

ใน Retrofit2 เมื่อคุณต้องการส่งพารามิเตอร์ของคุณในรูปแบบดิบคุณต้องใช้ Scalars

ก่อนอื่นให้เพิ่มสิ่งนี้ใน 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);

}

ตัวอย่างกิจกรรมของฉัน:

   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 ทั้งหมดแบบดิบในเนื้อหาของคำขอติดตั้งเพิ่มเติม


3

บางทีคุณอาจJSON Objectจะถูก แต่คำตอบที่คุณได้รับไม่ใช่ข้อมูลที่ถูกต้องเช่นเดียวกับเมื่อคุณเชื่อมต่อไม่ถูกต้องWiFiคุณอาจได้รับคำตอบแปลก ๆ< html>.....< /html>ว่าGSONไม่สามารถแยกวิเคราะห์ได้

คุณอาจต้องทำบางอย่างtry..catch..สำหรับการตอบสนองที่แปลกประหลาดนี้เพื่อหลีกเลี่ยงความผิดพลาด


3

ฉันได้มาแบ่งปันวิธีแก้ปัญหา เกิดข้อผิดพลาดกับฉันหลังจากบังคับให้สมุดบันทึกวางสาย clean prejectวิธีการแก้ปัญหาที่เป็นไปได้


3

ตรวจสอบให้แน่ใจว่าคุณมีอ็อบเจ็กต์ DESERIALIZED เช่น DATE / DATETIME เป็นต้นหากคุณส่ง JSON โดยตรงโดยไม่ต้อง deserializing ก็อาจทำให้เกิดปัญหานี้ได้


SERIALIZED ก่อนส่ง?
ratzip

@ratzip ขออภัยฉันหมายความว่าเราควรเพิ่ม deserializer (ตรรกะ) สำหรับวัตถุเช่น DATE | วันเวลา. ฉันประสบปัญหานี้เมื่อต้องการแมป JsonObject กับวัตถุ JAVA
Ravi Wadje

3

ในสถานการณ์ของฉันฉันมี "รูปแบบ" ประกอบด้วยพารามิเตอร์สตริงหลายยกเว้นหนึ่ง: 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 ฉันรู้ว่าฉันจำเป็นต้องมีรูปแบบบางอย่างในAdapterการแปลงBaseModelเป็น JsonObject การผสมผสานStringและbyte[]ในแบบจำลองจะทำให้เกิดความซับซ้อน เห็นได้ชัดว่า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 เป็น model ฉันใช้สิ่งต่อไปนี้:

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(ในกรณีนี้คือbyte[]คลาส) ผ่านAdapterทุกครั้งที่พบระหว่างการแปลงเป็น / เทียว JSONObject



0

ในกรณีของฉันฉันกำลังส่งคืนวัตถุ JSON เป็น

{"data": "", "message": "บันทึกการเข้าร่วมสำเร็จแล้ว .. !!!", "status": "success"}

แก้ไขได้โดยเปลี่ยนเป็น

{"data": {}, "message": "บันทึกการเข้าร่วมสำเร็จแล้ว .. !!!", "status": "success"}

ข้อมูลนี้เป็น JsonObject ย่อยและควรเริ่มจาก {not ""


0

หากรูปแบบและตัวแปร json ของคุณถูกต้องให้ตรวจสอบการสืบค้นฐานข้อมูลของคุณ ... แม้ว่าข้อมูลจะถูกบันทึกในฐานข้อมูลอย่างถูกต้องปัญหาที่แท้จริงอาจอยู่ในนั้น ... ตรวจสอบการสืบค้นของคุณอีกครั้งและลองอีกครั้ง .. หวังว่าจะช่วยได้


0

อย่าลืมแปลงวัตถุของคุณเป็น Json ก่อนโดยใช้ Gson ()

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

จากนั้นคุณสามารถแปลงกลับเป็นวัตถุได้อย่างง่ายดายโดยใช้ไลบรารีที่ยอดเยี่ยมนี้

      val fromUser = Gson().fromJson(fromUserJson, User::class.java)

0

ฉันมีกรณีที่ฉันอ่านจากไฟล์ json ที่เขียนด้วยลายมือ json นั้นสมบูรณ์แบบ อย่างไรก็ตามข้อผิดพลาดนี้เกิดขึ้น ดังนั้นฉันจึงเขียนจากวัตถุ java ไปยังไฟล์ json จากนั้นอ่านจากไฟล์ json นั้น ทุกอย่างเรียบร้อยดี ฉันไม่เห็นความแตกต่างระหว่าง json ที่เขียนด้วยลายมือและอันที่มาจากวัตถุ java พยายามเกินเปรียบเทียบแล้วไม่เห็นความแตกต่าง ในที่สุดฉันก็สังเกตเห็นขนาดไฟล์ทั้งสองแตกต่างกันเล็กน้อยและฉันใช้เครื่องมือ winHex และตรวจพบสิ่งพิเศษ ดังนั้นวิธีแก้ปัญหาสำหรับสถานการณ์ของฉันคือทำสำเนาไฟล์ json ที่ดีวางเนื้อหาลงในไฟล์และใช้

ใส่คำอธิบายภาพที่นี่

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.