วิธีการตรวจสอบว่าสตริงที่กำหนดเป็น JSON ที่ถูกต้องใน Java


155

ฉันจะตรวจสอบสตริง JSON ใน Java ได้อย่างไร หรือฉันจะแยกมันโดยใช้การแสดงออกปกติ?


ลองแยกวิเคราะห์ด้วย gson หรือไม่ การตรวจสอบผ่าน regex อาจไม่ใช่ความคิดที่ดี
aishwarya

2
json.orgมีลิงก์ไปยังตัวแยกวิเคราะห์จำนวนมาก
MartinK

คำตอบ:


261

แนวคิดที่ดีเยี่ยมลองแยกวิเคราะห์แล้วดูข้อยกเว้น:

import org.json.*;

public boolean isJSONValid(String test) {
    try {
        new JSONObject(test);
    } catch (JSONException ex) {
        // edited, to include @Arthur's comment
        // e.g. in case JSONArray is valid as well...
        try {
            new JSONArray(test);
        } catch (JSONException ex1) {
            return false;
        }
    }
    return true;
}

นี้จะใช้รหัสorg.jsonการดำเนิน JSON API ที่มีอยู่บน GitHub , ในผู้เชี่ยวชาญและมีบางส่วนบน Android


2
มันอยู่ใกล้ แต่จะหายไปตรวจสอบหา JSONArray (i ได้อัปเดตโพสต์นี้มีฟังก์ชั่นที่เหมาะสมกว่า)
อาร์เธอร์

9
ฉันได้ลองใช้สตริง json เช่น "{'hello': 'foo'} 'ไม่ถูกต้อง'" (เพิ่ม 'ไม่ถูกต้อง' นอก {}) และ JSONObject ไม่ได้โยน ParseException ฉันใช้ org.json.JSONObject คาดหวังหรือไม่
Soichi Hayashi

16
คุณไม่ได้พูดถึง
ไลบรารี่

6
วิธีนี้ใช้ได้ผลกับกรณีส่วนใหญ่ แต่อาจล้มเหลวในบางสถานการณ์ ตัวอย่างเช่นอนุญาตให้ใช้เครื่องหมายจุลภาคทันทีก่อนปิดวงเล็บปีกกาซึ่งจริงๆแล้วเป็นข้อผิดพลาดทางไวยากรณ์ อ้างถึงjson.org/javadoc/org/json/JSONObject.htmlสำหรับกรณีมุมอื่น ๆ
Hua2308

9
ฉันไม่เข้าใจว่าทำไมผู้โพสต์จึงไม่สามารถใส่ใจที่จะรวมคำสั่งการนำเข้ากับตัวอย่างโค้ด มันสำคัญที่นี่ คำตอบที่สองจัดอันดับที่นี่เป็นมากดีกว่า
seansand

100

ห้องสมุด JACKSON

ทางเลือกหนึ่งที่จะใช้ห้องสมุดแจ็คสัน ก่อนนำเข้าเวอร์ชันล่าสุด (ตอนนี้คือ):

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.7.0</version>
</dependency>

จากนั้นคุณสามารถใช้คำตอบที่ถูกต้องดังนี้

import com.fasterxml.jackson.databind.ObjectMapper;

public final class JSONUtils {
  private JSONUtils(){}

  public static boolean isJSONValid(String jsonInString ) {
    try {
       final ObjectMapper mapper = new ObjectMapper();
       mapper.readTree(jsonInString);
       return true;
    } catch (IOException e) {
       return false;
    }
  }
}

ตัวเลือก Google GSON

อีกตัวเลือกหนึ่งคือการใช้Google Gson นำเข้าการพึ่งพา:

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.5</version>
</dependency>

อีกครั้งคุณสามารถใช้วิธีแก้ไขปัญหาที่เสนอเป็น:

import com.google.gson.Gson;

public final class JSONUtils {
  private static final Gson gson = new Gson();

  private JSONUtils(){}

  public static boolean isJSONValid(String jsonInString) {
      try {
          gson.fromJson(jsonInString, Object.class);
          return true;
      } catch(com.google.gson.JsonSyntaxException ex) { 
          return false;
      }
  }
}

การทดสอบอย่างง่ายมีดังนี้:

//A valid JSON String to parse.
String validJsonString = "{ \"developers\": [{ \"firstName\":\"Linus\" , \"lastName\":\"Torvalds\" }, " +
        "{ \"firstName\":\"John\" , \"lastName\":\"von Neumann\" } ]}";

// Invalid String with a missing parenthesis at the beginning.
String invalidJsonString = "\"developers\": [ \"firstName\":\"Linus\" , \"lastName\":\"Torvalds\" }, " +
        "{ \"firstName\":\"John\" , \"lastName\":\"von Neumann\" } ]}";

boolean firstStringValid = JSONUtils.isJSONValid(validJsonString); //true
boolean secondStringValid = JSONUtils.isJSONValid(invalidJsonString); //false

โปรดสังเกตว่าอาจมี "ผู้เยาว์" 3.0.0ปัญหาเนื่องจากเครื่องหมายจุลภาคต่อท้ายว่าจะได้รับการแก้ไขในรุ่น


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

@eurythmia จริง! ในรุ่น 3.0 พวกเขาควรแก้ไขปัญหา
JeanValjean

1
สิ่งนี้จะตรวจสอบความถูกต้อง {key: value} ด้วย แต่ไม่ใช่ json ที่ถูกต้อง
Pratapi Hemant Patel

2
JACKSON หลุมพราง: new ObjectMapper().readTree("28xjRBuOQqupRopHeSuhRQ")แยกวิเคราะห์โดยไม่มีข้อยกเว้นเป็น IntNode (28) ไม่คาดหวังจริงๆ ...
mgaert

1
ที่ฉันเข้าใจโซลูชันนี้ไม่เพียง แต่ตรวจสอบ แต่แจง (และร้านค้า) json ทั้งหมด มันจะแปลงตัวเลขให้เป็นจำนวนเต็ม / ยาว / คู่ ฯลฯ นี่คือมากกว่าการตรวจสอบไวยากรณ์มันเก็บ json ทั้งหมดในหน่วยความจำ สิ่งนี้อาจมีความสำคัญสำหรับการใช้งานหนัก หากมีวิธีแก้ปัญหาที่ดีกว่าสำหรับการตรวจสอบไวยากรณ์?
javapowered

15

ด้วยGoogle Gsonคุณสามารถใช้ JsonParser:

import com.google.gson.JsonParser;

JsonParser parser = new JsonParser();
parser.parse(json_string); // throws JsonSyntaxException

3
โปรดทราบว่าสิ่งนี้จะไม่ส่งผลให้เกิดข้อผิดพลาดกับสตริงที่ไม่ได้แยกส่วน ala "asdf"
แอนดรู

1
ไม่ปฏิเสธคอมม่าต่อท้ายในอาร์เรย์ของ JSON
Sotirios Delimanolis

ฉันไม่สามารถเชื่อมั่นในสิ่งนั้นได้ ... มันบอกว่าสตริง "บันทึก" นั้นสามารถวิเคราะห์ได้
Dherik

ระวังตัวอย่าง gson ที่นี่ใช้โหมดการแยกวิเคราะห์แบบผ่อนปรนซึ่งยังอนุญาตการเบี่ยงเบนจำนวนมาก ดูรายละเอียดเพิ่มเติมกับ testcaseและตัวอย่างการแยกวิเคราะห์ที่เข้มงวดในคำตอบอื่น ๆ ของฉัน
Vadzim

14

คุณสามารถใช้. mayBeJSON (String str) ที่มีอยู่ในไลบรารีJSONUtils


ใช่ ... มันใช้งานได้ ขอบคุณ npinti ฉันพยายาม gson แต่ไม่มีวิธีดังกล่าวฉันได้เห็น
sappu

@sappu: หากคำตอบนี้แก้ไขคำถามของคุณแล้วทำเครื่องหมายว่าเป็นเช่นนั้น ไลบรารีส่วนใหญ่มักจะใช้สตริงและพยายามวิเคราะห์มันถ้าการแจงล้มเหลวนั่นคือสตริงนั้นไม่ใช่สตริง JSON ที่ถูกต้องมันจะส่งข้อยกเว้น
npinti

@npinti: ล้มเหลวเป็นพิเศษ} ผลตอบแทนจริงสำหรับสตริงที่ไม่ถูกต้องพร้อมเครื่องหมายพิเศษ =>}
Vivek

3
วิธีการนี้จะตรวจสอบอย่างแท้จริงว่าสตริงเริ่มต้นและสิ้นสุดด้วยเครื่องหมายคำพูดหรือวงเล็บ ไม่น่าเชื่อถือมาก
Michael Munsey

2
นั่นเป็นเหตุผลที่ชื่อวิธีการคือ 'อาจจะ' ไม่ใช่ 'คือ' :)
Khoa

5

ขึ้นอยู่กับสิ่งที่คุณพยายามพิสูจน์ด้วยการตรวจสอบของคุณ แน่นอนแจง json ตามที่คนอื่น ๆ แนะนำดีกว่าการใช้ regexes เพราะไวยากรณ์ของ json มีความซับซ้อนมากกว่าที่จะแสดงด้วยเพียงแค่ regexes

หาก json จะถูกแยกวิเคราะห์โดยรหัส java ของคุณเท่านั้นให้ใช้ตัวแยกวิเคราะห์ตัวเดียวกันเพื่อตรวจสอบความถูกต้อง

แต่การแยกวิเคราะห์ไม่จำเป็นต้องบอกคุณว่าจะยอมรับได้ในสภาพแวดล้อมอื่นหรือไม่ เช่น

  • ตัวแยกวิเคราะห์จำนวนมากละเว้นเครื่องหมายจุลภาคต่อท้ายในวัตถุหรืออาร์เรย์ แต่ IE เวอร์ชันเก่าอาจล้มเหลวเมื่อพวกเขากดเครื่องหมายจุลภาคต่อท้าย
  • ตัวแยกวิเคราะห์อื่น ๆ อาจยอมรับเครื่องหมายจุลภาคต่อท้าย แต่เพิ่มรายการ undefined / null หลังจากนั้น
  • ตัวแยกวิเคราะห์บางตัวอาจอนุญาตชื่อคุณสมบัติที่ไม่มีเครื่องหมายอัญประกาศ
  • ตัวแยกวิเคราะห์บางตัวอาจตอบสนองแตกต่างจากอักขระที่ไม่ใช่ ASCII ในสตริง

หากการตรวจสอบของคุณจะต้องละเอียดมากคุณสามารถ:

  • ลองใช้ parsers ที่แตกต่างกันจนกว่าคุณจะพบคนที่ล้มเหลวในทุกกรณีที่ฉันกล่าวถึงข้างต้น
  • หรือคุณอาจเรียกใช้ jsonlint โดยใช้ javax.script. *,
  • หรือรวมการใช้ parser กับการรัน jshint โดยใช้ javax.script. *

4
String jsonInput = "{\"mob no\":\"9846716175\"}";//Read input Here
JSONReader reader = new JSONValidatingReader();
Object result = reader.read(jsonInput);
System.out.println("Validation Success !!");

กรุณาดาวน์โหลดห้องสมุดstringtree-json


เป็นไปได้ไหมที่จะกำหนดสตริงเหมือนด้านบน? หรือเป็นเพียงไอเดีย
Santron Manibharathi

เป็นไปไม่ได้นั่นเป็นเพราะความผิดพลาดของฉันรับทราบแล้วมันถูกต้อง
ขอบคุณ

1
JSONValidatingReaderไม่ได้เป็นส่วนหนึ่งของ Java API
IgorGanapolsky

กรุณาใช้ห้องสมุดดังกล่าวข้างต้นขอบคุณ
Jamsheer

2

เล็กน้อยเกี่ยวกับการแยกวิเคราะห์:

Json และในความเป็นจริงทุกภาษาใช้ไวยากรณ์ซึ่งเป็นชุดของกฎที่สามารถใช้แทน ในการแยกวิเคราะห์ json คุณจำเป็นต้องใช้การแทนที่เหล่านั้นในทางกลับกัน

Json เป็นไวยากรณ์แบบไม่มีบริบทหมายความว่าคุณสามารถมีออบเจ็กต์ / อาร์เรย์ซ้อนกันอย่างไม่สิ้นสุดและ json จะยังคงใช้งานได้ regex จัดการเฉพาะไวยากรณ์ปกติ (ดังนั้น 'reg' ในชื่อ) ซึ่งเป็นส่วนหนึ่งของไวยากรณ์ฟรีบริบทที่ไม่อนุญาตให้มีการทำรังที่ไม่มีที่สิ้นสุดดังนั้นจึงเป็นไปไม่ได้ที่จะใช้เฉพาะ regex เพื่อแจง json ที่ถูกต้องทั้งหมด คุณสามารถใช้ชุด regex ที่ซับซ้อนและวนซ้ำกับข้อสันนิษฐานที่ไม่มีใครทำรังในอดีตพูดลึก 100 ระดับ แต่มันก็ยังคงเป็นเรื่องยากมาก

ถ้าคุณพร้อมที่จะเขียน parser ของคุณเอง
คุณสามารถสร้าง parser ที่สืบเชื้อสายมาจากคุณหลังจากที่คุณใช้ไวยากรณ์


2

ตรวจสอบไม่ว่าจะเป็นสตริงที่กำหนดเป็น JSON ที่ถูกต้องในKotlin ฉันแปลงคำตอบของMByD Java เป็น Kotlin

fun isJSONValid(test: String): Boolean {
    try {
        JSONObject(test);
    } catch (ex: JSONException) {
        try {
            JSONArray(test);
        } catch (ex1: JSONException) {
            return false;
        }
    }
    return true;
}

1

ที่นี่คุณสามารถค้นหาเครื่องมือที่สามารถตรวจสอบความถูกต้องของไฟล์ JSON หรือคุณสามารถทำการ deserialize ไฟล์ JSON ของคุณกับไลบรารี่ JSON ใดก็ได้และหากการดำเนินการประสบความสำเร็จก็ควรจะถูกต้อง ( google-jsonเป็นต้น) มันคือการแยกไม่ถูกต้อง JSON)


1

เมื่อใช้ Playframework 2.6 ไลบรารี Json ที่พบใน java api สามารถใช้เพื่อแยกสตริงได้อย่างง่ายดาย สตริงสามารถเป็นองค์ประกอบ json ของอาร์เรย์ json เนื่องจากค่าที่ส่งคืนไม่มีความสำคัญที่นี่เราเพิ่งจับข้อผิดพลาดในการแยกวิเคราะห์เพื่อตรวจสอบว่าสตริงเป็นสตริง json ที่ถูกต้องหรือไม่

    import play.libs.Json;

    public static Boolean isValidJson(String value) {
        try{
            Json.parse(value);
            return true;
        } catch(final Exception e){
            return false;
        }
    }

1

IMHO วิธีที่สง่างามมากที่สุดคือการใช้ใน Java API สำหรับ JSON การประมวลผล (JSON-P) ซึ่งเป็นหนึ่งในมาตรฐาน JavaEE ที่สอดคล้องกับJSR 374

try(StringReader sr = new StringReader(jsonStrn)) {
    Json.createReader(sr).readObject();
} catch(JsonParsingException e) {
    System.out.println("The given string is not a valid json");
    e.printStackTrace();
}

ใช้ Maven เพิ่มการพึ่งพา JSON-P:

<dependency>
    <groupId>org.glassfish</groupId>
    <artifactId>javax.json</artifactId>
    <version>1.1.4</version>
</dependency>

เยี่ยมชมหน้าอย่างเป็นทางการของ JSON-Pสำหรับข้อมูลเพิ่มเติม


1

นี่คือตัวอย่างการทำงานสำหรับการแยกวิเคราะห์ json ที่เข้มงวดกับไลบรารีgson :

public static JsonElement parseStrict(String json) {
    // throws on almost any non-valid json
    return new Gson().getAdapter(JsonElement.class).fromJson(json); 
}

ดูคำตอบโดยละเอียดอื่น ๆ ของฉันในวิธีตรวจสอบว่า JSON นั้นถูกต้องใน Java โดยใช้ GSONด้วยข้อมูลเพิ่มเติมและกรณีทดสอบเพิ่มเติมพร้อมตัวอย่างที่ไม่ถูกต้องมากมาย


1

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

แต่ขึ้นอยู่กับบริบทคุณอาจปรับปรุงการแสดงด้วยการตรวจสอบล่วงหน้า

สิ่งที่ฉันทำเมื่อฉันเรียก API คือตรวจสอบว่าอักขระตัวแรกคือ '{' และตัวสุดท้ายคือ '}' ถ้าไม่ใช่ในกรณีนี้ฉันจะไม่สร้าง parser


0

ฉันได้พบวิธีแก้ปัญหาที่ง่ายมากสำหรับมันแล้ว

กรุณาติดตั้งไลบรารีนี้net.sf.json-libก่อน

    import net.sf.json.JSONException;

    import net.sf.json.JSONSerializer;

    private static boolean isValidJson(String jsonStr) {
        boolean isValid = false;
        try {
            JSONSerializer.toJSON(jsonStr);
            isValid = true;
        } catch (JSONException je) {
            isValid = false;
        }
        return isValid;
    }

    public static void testJson() {
        String vjson = "{\"employees\": [{ \"firstName\":\"John\" , \"lastName\":\"Doe\" },{ \"firstName\":\"Anna\" , \"lastName\":\"Smith\" },{ \"firstName\":\"Peter\" , \"lastName\":\"Jones\" }]}";
        String ivjson = "{\"employees\": [{ \"firstName\":\"John\" ,, \"lastName\":\"Doe\" },{ \"firstName\":\"Anna\" , \"lastName\":\"Smith\" },{ \"firstName\":\"Peter\" , \"lastName\":\"Jones\" }]}";
        System.out.println(""+isValidJson(vjson)); // true
        System.out.println(""+isValidJson(ivjson)); // false
    }

เสร็จสิ้น สนุก


0

คำตอบนั้นถูกต้องเพียงบางส่วน ฉันยังประสบปัญหาเดียวกัน การแยกวิเคราะห์ json และตรวจสอบข้อยกเว้นดูเหมือนเป็นวิธีปกติ แต่วิธีแก้ปัญหาล้มเหลวสำหรับอินพุต json บางอย่างเช่น

{"outputValueSchemaFormat": "", "sortByIndexInRecord": 0, "sortOrder": 847874874387209 "จากมากไปน้อย"} kajhfsadkjh

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

หาวิธีการแก้ปัญหานี้ดูที่นี่

PS: คำถามนี้ถูกถามและตอบโดยฉัน



0
public static boolean isJSONValid(String test) {
    try {
        isValidJSON(test);
        JsonFactory factory = new JsonFactory();
        JsonParser parser = factory.createParser(test);
        while (!parser.isClosed()) {
            parser.nextToken();
        }
    } catch (Exception e) {
        LOGGER.error("exception: ", e);
        return false;
    }
    return true;
}

private static void isValidJSON(String test) {
    try {
        new JSONObject(test);
    } catch (JSONException ex) {
        try {
            LOGGER.error("exception: ", ex);
            new JSONArray(test);
        } catch (JSONException ex1) {
            LOGGER.error("exception: ", ex1);
            throw new Exception("Invalid JSON.");
        }
    }
}

วิธีการแก้ปัญหาข้างต้นครอบคลุมทั้งสองสถานการณ์:

  • รหัสซ้ำ
  • คำพูดไม่ตรงกันหรือวงเล็บหายไป ฯลฯ

0

วิธีแก้ปัญหาโดยใช้javax.jsonไลบรารี:

import javax.json.*;

public boolean isTextJson(String text) {
    try {
        Json.createReader(new StringReader(text)).readObject();
    } catch (JsonException ex) {
        try {
            Json.createReader(new StringReader(text)).readArray();
        } catch (JsonException ex2) {
            return false;
        }
    }
    return true;
}

0

คุณสามารถใช้WellFormedJsonคลาสได้จากไลบรารีการตรวจสอบความถูกต้องของValidol

การประกาศตัวเองอาจมีลักษณะดังต่อไปนี้:

new WellFormedJson(
    new Unnamed<>(Either.right(new Present<>(jsonRequestString)))
)

ขั้นตอนการตรวจสอบมีลักษณะดังนี้:

    Result<JsonElement> result =
        (new WellFormedJson(
            new Named<>(
                "vasya",
                Either.right(
                    new Present<>(
                        "{\"guest\":{\"name\":\"Vadim Samokhin\",\"email\":\"samokhinvadim@gmail.com\"},\"source\":1,\"items\":[{\"id\":1900},{\"id\":777}]}"
                    )
                )
            )
        ))
            .result();

    assertTrue(result.isSuccessful());
    assertEquals(
        "{\"guest\":{\"name\":\"Vadim Samokhin\",\"email\":\"samokhinvadim@gmail.com\"},\"source\":1,\"items\":[{\"id\":1900},{\"id\":777}]}",
        result.value().raw().toString()
    );
    assertEquals(
        "{\"name\":\"Vadim Samokhin\",\"email\":\"samokhinvadim@gmail.com\"}",
        result.value().raw().getAsJsonObject().get("guest").toString()
    );

อาจดูเหมือน overkill สำหรับงานง่าย ๆ แต่มันจะส่องแสงเมื่อคุณต้องตรวจสอบคำขอที่ซับซ้อน ตรวจสอบ validol ของส่วนเริ่มต้นอย่างรวดเร็ว

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