Cách kiểm tra xem một chuỗi đã cho có phải là JSON hợp lệ trong Java không


155

Làm cách nào để xác thực chuỗi JSON trong Java? Hoặc tôi có thể phân tích nó bằng cách sử dụng các biểu thức thông thường?


thử phân tích cú pháp với gson? xác nhận thông qua regex có thể không phải là một ý tưởng hay
aishwarya

2
json.org có liên kết đến rất nhiều trình phân tích cú pháp
MartinK

Câu trả lời:


261

Một ý tưởng hoang dã, hãy thử phân tích cú pháp và bắt ngoại lệ:

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;
}

Mã này sử dụng triển khai API org.json có sẵn trên github , trong maven và một phần trên Android .


2
Nó rất gần, nhưng thiếu một xác thực cho một JSONArray (tôi đã cập nhật bài đăng này với một chức năng phù hợp hơn)
Arthur

9
Tôi đã thử một chuỗi json như "{'xin chào': 'foo'} 'không hợp lệ'" (đã thêm 'không hợp lệ' bên ngoài {}) và JSONObject không ném ParseException. Tôi đang sử dụng org.json.JSONObject. Đây có phải là mong đợi?
Soichi Hayashi

16
Bạn đã không đề cập đến thư viện có JSONObject, tôi đã không thấy nó trong java lib tiêu chuẩn
Krzysztof Krasnoyń

6
Giải pháp này hoạt động trong hầu hết các trường hợp, nhưng có thể thất bại trong một số trường hợp nhất định. Ví dụ, nó cho phép dấu phẩy ngay trước dấu ngoặc đóng, đây thực sự là một lỗi cú pháp. Tham khảo json.org/javadoc/org/json/JSONObject.html để biết các trường hợp góc khác.
Hua2308

9
Tôi không thể hiểu tại sao người đăng không thể bận tâm để bao gồm các báo cáo nhập khẩu với đoạn mã. Nó quan trọng ở đây. Câu trả lời thứ hai ở đây tốt hơn nhiều .
seansand

100

Thư viện JACKSON

Một lựa chọn sẽ là sử dụng thư viện Jackson . Lần đầu tiên nhập phiên bản mới nhất (bây giờ là):

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

Sau đó, bạn có thể thực hiện câu trả lời đúng như sau:

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;
    }
  }
}

Tùy chọn Google GSON

Một tùy chọn khác là sử dụng Google Gson . Nhập phụ thuộc:

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

Một lần nữa, bạn có thể thực hiện giải pháp đề xuất như:

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;
      }
  }
}

Một bài kiểm tra đơn giản sau đây:

//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

Xin vui lòng, quan sát rằng có thể có một vấn đề "nhỏ" do dấu phẩy sẽ được khắc phục trong bản phát hành 3.0.0.


Trong khi điều này hoạt động cho những thứ lớn như trích dẫn không khớp hoặc dấu ngoặc đơn bị thiếu, Gson sẽ vui vẻ phân tích một mảng json bằng dấu phẩy, không tuân theo RFC-4627
eury nhịpia

@eury nhịpia Đúng! Trong phiên bản 3.0, họ sẽ khắc phục sự cố
JeanValjean

1
Điều này cũng xác nhận {key: value}, nhưng nó không phải là json hợp lệ
Pratapi Hemant Patel

2
Cạm bẫy của JACKSON: new ObjectMapper().readTree("28xjRBuOQqupRopHeSuhRQ")phân tích cú pháp mà không có Ngoại lệ là IntNode (28). Không thực sự mong đợi ...
mgaert

1
Theo tôi hiểu giải pháp này không chỉ xác nhận, mà còn phân tích (và lưu trữ) toàn bộ json. Nó chuyển đổi số thành Integer / Long / Double, v.v ... Đây không chỉ là kiểm tra cú pháp, nó lưu toàn bộ json trong bộ nhớ. Điều này có thể có ý nghĩa đối với tải trọng cao. Nếu giải pháp tốt hơn cho kiểm tra cú pháp tồn tại?
javapowered

15

Với Google Gson, bạn có thể sử dụng JsonParser:

import com.google.gson.JsonParser;

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

3
Lưu ý rằng điều này không gây ra lỗi đối với các chuỗi không được đặt tên là "asdf"
Andrew

1
Nó cũng không từ chối dấu phẩy trong mảng JSON.
Sotirios Delimanolis

Tôi thực sự không thể tin vào điều đó ... nó nói rằng chuỗi "Lưu" có thể phân tích cú pháp.
Dherik

Coi chừng ví dụ gson ở đây sử dụng chế độ phân tích cú pháp nhẹ nhàng mà vẫn cho phép nhiều sai lệch. Xem thêm chi tiết với testcaseví dụ phân tích nghiêm ngặt trong các câu trả lời khác của tôi.
Vadzim

14

Bạn có thể sử dụng .mayBeJSON (Chuỗi str) có sẵn trong thư viện JSONUtils .


vâng ... điều này đang hoạt động. Cảm ơn npinti. tôi đã thử với gson nhưng tôi không thấy phương pháp nào như vậy.
sappu

@sappu: Nếu câu trả lời này giải quyết được câu hỏi của bạn thì hãy đánh dấu nó như vậy. Hầu hết các thư viện có xu hướng lấy một Chuỗi và cố gắng phân tích nó, nếu phân tích cú pháp thất bại, nghĩa là chuỗi không phải là một chuỗi JSON hợp lệ, nó sẽ đưa ra một ngoại lệ.
npinti

@npinti: Không thể thêm}. Trả về true cho chuỗi không hợp lệ có dấu ngoặc phụ =>}
Vivek

3
Phương thức này theo nghĩa đen chỉ kiểm tra xem chuỗi bắt đầu và kết thúc bằng dấu ngoặc kép hay dấu ngoặc. Rất không đáng tin cậy.
Michael Munsey

2
đó là lý do tại sao tên phương thức là 'có thể', không phải 'là' :)
Khoa

5

Nó phụ thuộc vào những gì bạn đang cố gắng chứng minh với xác nhận của bạn. Chắc chắn phân tích cú pháp json như những người khác đã đề xuất là tốt hơn so với sử dụng regexes, bởi vì ngữ pháp của json phức tạp hơn có thể được biểu diễn chỉ bằng regexes.

Nếu json sẽ chỉ được phân tích cú pháp bởi mã java của bạn, thì hãy sử dụng cùng một trình phân tích cú pháp để xác thực nó.

Nhưng chỉ cần phân tích cú pháp sẽ không nhất thiết cho bạn biết nếu nó sẽ được chấp nhận trong các môi trường khác. ví dụ

  • nhiều trình phân tích cú pháp bỏ qua dấu phẩy trong một đối tượng hoặc mảng, nhưng các phiên bản IE cũ có thể thất bại khi chúng chạm vào dấu phẩy.
  • Các trình phân tích cú pháp khác có thể chấp nhận dấu phẩy, nhưng thêm một mục không xác định / null sau nó.
  • Một số trình phân tích cú pháp có thể cho phép tên thuộc tính không trích dẫn.
  • Một số trình phân tích cú pháp có thể phản ứng khác nhau với các ký tự không phải ASCII trong chuỗi.

Nếu xác nhận của bạn cần phải rất kỹ lưỡng, bạn có thể:


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

Vui lòng tải xuống thư viện stringtree-json


Có thể định nghĩa một Chuỗi như trên không? Hoặc đó chỉ là ý tưởng.
Santron Manibharathi

không thể, đó là do sai lầm của tôi
Bây giờ

1
JSONValidatingReader không phải là một phần của API Java
IgorGanapolsky

Vui lòng sử dụng thư viện được đề cập ở trên, Cảm ơn
Jamsheer

2

Một chút về phân tích cú pháp:

Json, và trên thực tế tất cả các ngôn ngữ, sử dụng một ngữ pháp là một bộ quy tắc có thể được sử dụng thay thế. để phân tích json, về cơ bản, bạn cần phải tìm ra những sự thay thế đó

Json là một ngữ pháp không có ngữ cảnh , nghĩa là bạn có thể có các đối tượng / mảng được lồng vô hạn và json vẫn sẽ hợp lệ. regex chỉ xử lý các ngữ pháp thông thường (do đó là 'reg' trong tên), là một tập hợp con của các ngữ pháp tự do ngữ cảnh không cho phép lồng nhau vô hạn, vì vậy không thể chỉ sử dụng regex để phân tích tất cả json hợp lệ. bạn có thể sử dụng một tập hợp các regex và vòng lặp phức tạp với giả định rằng không ai sẽ nói quá khứ, sâu 100 cấp độ, nhưng nó vẫn sẽ rất khó khăn.

nếu bạn sẵn sàng viết trình phân tích cú pháp của riêng mình,
bạn có thể tạo một trình phân tích cú pháp gốc đệ quy sau khi bạn thực hiện ngữ pháp


2

Kiểm tra xem một chuỗi đã cho có phải là JSON hợp lệ trong Kotlin không . Tôi đã chuyển đổi câu trả lời của MByD Java sang Kotlin

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

1

Tại đây, bạn có thể tìm thấy một công cụ có thể xác thực tệp JSON hoặc bạn chỉ có thể giải tuần tự hóa tệp JSON của mình với bất kỳ thư viện JSON nào và nếu thao tác thành công thì nó phải hợp lệ ( ví dụ google-json sẽ ném ngoại lệ nếu đầu vào nó đang phân tích cú pháp không hợp lệ JSON).


1

Sử dụng Playframework 2.6, thư viện Json được tìm thấy trong java api cũng có thể được sử dụng để phân tích chuỗi đơn giản. Chuỗi có thể là một phần tử json của mảng json. Vì giá trị trả về không quan trọng ở đây, chúng tôi chỉ cần bắt lỗi phân tích cú pháp để xác định rằng chuỗi có phải là chuỗi json chính xác hay không.

    import play.libs.Json;

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

1

IMHO, cách thanh lịch nhất là sử dụng API Java để xử lý JSON (JSON-P), một trong những tiêu chuẩn JavaEE phù hợp với 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();
}

Sử dụng Maven, thêm phụ thuộc vào JSON-P:

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

Truy cập trang chính thức JSON-P để biết thêm thông tin.


1

Dưới đây là một ví dụ hoạt động để phân tích cú pháp json nghiêm ngặt với thư viện gson :

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

Xem thêm câu trả lời chi tiết khác của tôi trong Cách kiểm tra xem JSON có hợp lệ trong Java hay không bằng cách sử dụng GSON với nhiều thông tin hơn và trường hợp thử nghiệm mở rộng với các ví dụ không hợp lệ khác nhau.


1

Như bạn có thể thấy, có rất nhiều giải pháp, họ chủ yếu phân tích cú pháp JSON để kiểm tra và cuối cùng bạn sẽ phải phân tích cú pháp để chắc chắn.

Nhưng, tùy thuộc vào ngữ cảnh, bạn có thể cải thiện màn trình diễn bằng cách kiểm tra trước.

Những gì tôi làm khi tôi gọi API, chỉ là kiểm tra xem ký tự đầu tiên là '{' và cuối cùng là '}'. Nếu không phải như vậy, tôi không bận tâm đến việc tạo một trình phân tích cú pháp.


0

Tôi đã tìm thấy một giải pháp rất đơn giản cho nó.

Trước tiên hãy cài đặt thư viện này net.sf.json-libcho nó.

    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
    }

Làm xong. Thưởng thức


0

Các câu trả lời là một phần chính xác. Tôi cũng phải đối mặt với vấn đề tương tự. Phân tích cú pháp json và kiểm tra ngoại lệ có vẻ như cách thông thường nhưng giải pháp không thành công cho json đầu vào giống như

{"outputValueSchemaFormat": "", "sortByIndexInRecord": 0, "sortOrder": 847874874387209 "giảm dần"} kajhfsadkjh

Như bạn có thể thấy json không hợp lệ vì có các ký tự rác. Nhưng nếu bạn cố phân tích json ở trên bằng cách sử dụng jackson hoặc gson thì bạn sẽ nhận được bản đồ được phân tích cú pháp của json hợp lệ và các ký tự theo dõi rác được bỏ qua. Đó không phải là giải pháp cần thiết khi bạn đang sử dụng trình phân tích cú pháp để kiểm tra tính hợp lệ của json.

Để biết giải pháp cho vấn đề này xem tại đây .

PS: Câu hỏi này đã được tôi hỏi và trả lời.


0
import static net.minidev.json.JSONValue.isValidJson;

và sau đó gọi hàm này đi qua Chuỗi JSON của bạn :)


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.");
        }
    }
}

Giải pháp trên bao gồm cả hai kịch bản:

  • khóa trùng lặp
  • trích dẫn không khớp hoặc dấu ngoặc đơn bị thiếu, vv

0

Một giải pháp sử dụng javax.jsonthư viện:

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

Bạn có thể sử dụng WellFormedJsonlớp từ Validol thư viện xác nhận khai báo.

Bản khai có thể trông giống như sau:

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

Giai đoạn kiểm tra trông như thế:

    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()
    );

Nó có vẻ như quá mức cho một nhiệm vụ đơn giản như vậy, nhưng nó tỏa sáng khi bạn phải xác nhận một yêu cầu phức tạp. Kiểm tra phần bắt đầu nhanh chóng của validol .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.