Cara memeriksa apakah string yang diberikan JSON valid di Jawa

155

Bagaimana cara memvalidasi string JSON di Java? Atau bisakah saya menguraikannya menggunakan ekspresi reguler?

sappu
sumber
coba parsing dengan gson? memvalidasi melalui regex mungkin bukan ide yang baik
aishwarya
2
json.org memiliki tautan ke sangat banyak parser
MartinK

Jawaban:

261

Gagasan liar, coba parsing dan tangkap pengecualian:

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

Kode ini menggunakan implementasi JSON API org.json yang tersedia di github , dalam maven dan sebagian di Android .

MByD
sumber
2
Itu dekat, tetapi tidak ada validasi untuk JSONArray (saya telah memperbarui posting ini dengan fungsi yang lebih cocok)
Arthur
9
Saya sudah mencoba string json seperti "{'hello': 'foo'} 'invalid'" (ditambahkan 'invalid' di luar {}), dan JSONObject tidak melempar ParseException. Saya menggunakan org.json.JSONObject. Apakah ini yang diharapkan?
Soichi Hayashi
16
Anda tidak menyebutkan perpustakaan yang memiliki JSONObject, saya tidak melihatnya di lib java standar
Krzysztof Krasoń
6
Solusi ini berfungsi untuk sebagian besar kasus, tetapi bisa gagal dalam kondisi tertentu. Misalnya, memungkinkan koma tepat sebelum kurung kurawal, yang sebenarnya merupakan kesalahan sintaksis. Rujuk ke json.org/javadoc/org/json/JSONObject.html untuk kasus sudut lainnya.
Hua2308
9
Saya tidak mengerti mengapa poster tidak dapat diganggu untuk memasukkan pernyataan impor dengan potongan kode. Ini penting di sini. Jawaban peringkat kedua di sini jauh lebih baik.
seansand
100

Perpustakaan JACKSON

Salah satu opsi adalah menggunakan perpustakaan Jackson . Impor versi terbaru (sekarang adalah):

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

Kemudian, Anda dapat menerapkan jawaban yang benar sebagai berikut:

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

Opsi Google GSON

Pilihan lain adalah menggunakan Google Gson . Impor ketergantungan:

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

Sekali lagi, Anda dapat mengimplementasikan solusi yang diusulkan sebagai:

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

Tes sederhana berikut di sini:

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

Harap perhatikan bahwa mungkin ada masalah "minor" karena trailing koma yang akan diperbaiki dalam rilis 3.0.0.

JeanValjean
sumber
Meskipun ini berfungsi untuk hal-hal besar seperti kutipan yang tidak cocok, atau tanda kurung yang hilang, Gson akan dengan senang hati mengurai array json dengan koma trailing, yang tidak sesuai dengan RFC-4627
eurythmia
@eurythmia Benar! Dalam versi 3.0 mereka harus memperbaiki masalah ini
JeanValjean
1
Ini memvalidasi {key: value} juga, tetapi itu bukan json yang valid
Pratapi Hemant Patel
2
JACKSON pitfall: new ObjectMapper().readTree("28xjRBuOQqupRopHeSuhRQ")mem-parsing tanpa Exception as IntNode (28). Tidak terlalu diharapkan ...
mgaert
1
Seperti yang saya mengerti solusi ini tidak hanya memvalidasi, tetapi mem-parsing (dan menyimpan) seluruh json. Ini mengkonversi angka ke Integer / Long / Double dll. Ini lebih dari sekedar pemeriksaan sintaks, ia menyimpan seluruh json dalam memori. Ini mungkin penting untuk beban intensif. Jika ada solusi yang lebih baik untuk pemeriksaan sintaks?
javapowered
15

Dengan Google Gson Anda dapat menggunakan JsonParser:

import com.google.gson.JsonParser;

JsonParser parser = new JsonParser();
parser.parse(json_string); // throws JsonSyntaxException
Cristian
sumber
3
Perhatikan bahwa ini tidak menimbulkan kesalahan pada string unbracketed ala "asdf"
Andrew
1
Juga tidak menolak tanda koma di array JSON.
Sotirios Delimanolis
Saya benar-benar tidak bisa mempercayai itu ... ia mengatakan bahwa string "Simpan" dapat diuraikan.
Dherik
Waspadalah bahwa contoh gson di sini menggunakan mode parsing ringan yang masih memungkinkan banyak penyimpangan. Lihat lebih detail dengan testcase dan contoh parsing ketat di jawaban saya yang lain.
Vadzim
14

Anda bisa menggunakan .mayBeJSON (String str) yang tersedia di perpustakaan JSONUtils .

npinti
sumber
ya ... ini berhasil. Terima kasih npinti. Saya mencoba dengan gson tetapi tidak ada metode yang saya lihat.
sappu
@sappu: Jika jawaban ini menyelesaikan pertanyaan Anda, maka tandai begitu. Sebagian besar pustaka cenderung untuk mengambil String dan mencoba untuk menguraikannya, jika parsing gagal, yaitu, string tersebut bukan string JSON yang valid, itu akan mengeluarkan pengecualian.
npinti
@npinti: Gagal tambahan}. Mengembalikan nilai true untuk string yang tidak valid dengan braket tambahan =>}
Vivek
3
Metode ini secara harfiah hanya memeriksa bahwa string dimulai dan diakhiri dengan tanda kutip atau tanda kurung. Sangat tidak bisa diandalkan.
Michael Munsey
2
itu sebabnya nama metode adalah 'mungkin', bukan 'adalah' :)
Khoa
5

Itu tergantung pada apa yang Anda coba buktikan dengan validasi Anda. Tentu saja mengurai json seperti yang orang lain sarankan lebih baik daripada menggunakan regex, karena tata bahasa json lebih rumit daripada yang bisa diwakili dengan hanya regex.

Jika json hanya akan diuraikan oleh kode java Anda, maka gunakan parser yang sama untuk memvalidasinya.

Tetapi hanya parsing tidak selalu memberi tahu Anda apakah itu akan diterima di lingkungan lain. misalnya

  • banyak parser mengabaikan tanda koma di suatu objek atau array, tetapi versi lama IE bisa gagal ketika mereka menekan tanda koma.
  • Parser lain mungkin menerima koma trailing, tetapi menambahkan entri tidak terdefinisi / null setelahnya.
  • Beberapa parser mungkin mengizinkan nama properti yang tidak dikutip.
  • Beberapa parser dapat bereaksi secara berbeda terhadap karakter non-ASCII dalam string.

Jika validasi Anda harus sangat menyeluruh, Anda dapat:

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

Silakan unduh perpustakaan stringtree-json

Jamsheer
sumber
Apakah mungkin untuk mendefinisikan String seperti di atas? Atau itu hanya untuk Ide.
Santron Manibharathi
tidak mungkin, itu karena kesalahan saya. sekarang ini dikoreksi. Terima kasih
Jamsheer
1
JSONValidatingReader bukan bagian dari Java API
IgorGanapolsky
Silakan gunakan perpustakaan yang disebutkan di atas, Terima kasih
Jamsheer
2

Sedikit tentang parsing:

Json, dan bahkan semua bahasa, menggunakan tata bahasa yang merupakan seperangkat aturan yang dapat digunakan sebagai pengganti. untuk mem-parse json, Anda pada dasarnya harus mengerjakan penggantian itu secara terbalik

Json adalah tata bahasa bebas konteks , yang berarti Anda dapat memiliki objek / array yang tak terbatas bersarang dan json akan tetap valid. regex hanya menangani tata bahasa reguler (karenanya 'reg' dalam nama), yang merupakan bagian dari tata bahasa bebas konteks yang tidak memungkinkan bersarang tanpa batas, jadi tidak mungkin untuk menggunakan hanya regex untuk mem-parsing semua json yang valid. Anda bisa menggunakan satu set regex yang rumit dan loop dengan asumsi bahwa tidak ada yang akan bersarang melewati, 100 level dalam, tetapi itu masih akan sangat sulit.

jika Anda bangun untuk menulis parser
Anda sendiri, Anda bisa membuat parser keturunan rekursif setelah Anda menyusun tata bahasa

Austin_Anderson
sumber
2

Periksa apakah string yang diberikan adalah JSON yang valid di Kotlin . Saya mengonversi jawaban MByD Java ke Kotlin

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

Di sini Anda dapat menemukan alat yang dapat memvalidasi file JSON, atau Anda bisa membatalkan deserialisasi file JSON Anda dengan pustaka JSON mana pun dan jika operasi berhasil maka itu harus valid ( google-json misalnya yang akan memberikan pengecualian jika input itu parsing bukan JSON yang valid).

talnicolas
sumber
1

Menggunakan Playframework 2.6, pustaka Json yang ditemukan di java api juga dapat digunakan untuk mengurai string. String dapat berupa elemen json dari json array. Karena nilai yang dikembalikan tidak penting di sini kita hanya menangkap kesalahan parse untuk menentukan bahwa string tersebut adalah string json yang benar atau tidak.

    import play.libs.Json;

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

IMHO, cara paling elegan adalah menggunakan Java API untuk JSON Processing (JSON-P), salah satu standar JavaEE yang sesuai dengan 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();
}

Menggunakan Maven, tambahkan ketergantungan pada JSON-P:

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

Kunjungi halaman resmi JSON-P untuk informasi lebih lanjut.

Domenico
sumber
1

Berikut adalah contoh kerja untuk parsing json ketat dengan pustaka gson :

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

Lihat juga jawaban terperinci saya yang lain di Cara memeriksa apakah JSON valid di Java menggunakan GSON dengan info lebih lanjut dan perpanjangan test case dengan berbagai contoh tidak valid.

Vadzim
sumber
1

Seperti yang Anda lihat, ada banyak solusi, mereka sebagian besar mengurai JSON untuk memeriksanya dan pada akhirnya Anda harus menguraikannya untuk memastikan.

Tetapi, tergantung pada konteksnya, Anda dapat meningkatkan kinerja dengan pemeriksaan awal.

Apa yang saya lakukan ketika saya memanggil API, hanya memeriksa bahwa karakter pertama adalah '{' dan yang terakhir adalah '}'. Jika bukan itu masalahnya, saya tidak perlu repot-repot membuat parser.

Orden
sumber
0

Saya telah menemukan solusi yang sangat sederhana untuk itu.

Silakan instal pustaka ini terlebih dahulu net.sf.json-libuntuk itu.

    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
    }

Selesai Nikmati

Atif Mehar
sumber
0

Jawabannya sebagian benar. Saya juga menghadapi masalah yang sama. Mem-parsing json dan memeriksa pengecualian sepertinya cara biasa tetapi solusi gagal untuk input json seperti

{"outputValueSchemaFormat": "", "sortByIndexInRecord": 0, "sortOrder": 847874874387209 "descending"} kajhfsadkjh

Seperti yang Anda lihat, json tidak valid karena ada karakter jejak trailing. Tetapi jika Anda mencoba mem-parsing json di atas menggunakan jackson atau gson maka Anda akan mendapatkan peta parsing dari json yang valid dan karakter sisa jejak diabaikan. Yang bukan solusi yang diperlukan ketika Anda menggunakan parser untuk memeriksa validitas json.

Untuk solusi masalah ini lihat di sini .

PS: Pertanyaan ini diajukan dan dijawab oleh saya.

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

dan kemudian panggil fungsi ini lewat JSON String Anda :)

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

Solusi di atas mencakup kedua skenario:

  • kunci duplikat
  • kutipan yang tidak cocok atau tanda kurung yang hilang dll.
Shailendra
sumber
0

Solusi menggunakan javax.jsonperpustakaan:

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;
}
ya
sumber
0

Anda dapat menggunakan WellFormedJsonkelas dari pustaka validasi deklaratif Validol .

Deklarasi itu sendiri dapat terlihat seperti berikut:

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

Fase pemeriksaan terlihat seperti itu:

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

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

Ini mungkin tampak seperti kerja keras untuk tugas sederhana seperti itu, tetapi bersinar ketika Anda harus memvalidasi permintaan yang kompleks. Lihat bagian mulai cepat validol .

Vadim Samokhin
sumber