Java'da belirli bir dizenin geçerli JSON olup olmadığını kontrol etme


155

Java'da bir JSON dizesini nasıl doğrularım? Yoksa düzenli ifadeler kullanarak ayrıştırabilir miyim?


gson ile ayrışmayı denemek ister misiniz? regex ile doğrulama iyi bir fikir olmayabilir
aishwarya

2
json.org çok sayıda ayrıştırıcıya bağlantı veriyor
MartinK

Yanıtlar:


261

Çılgın bir fikir, ayrıştırmayı deneyin ve istisnayı yakalayın:

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

Bu kod , github , maven ve kısmen Android'de bulunan org.json JSON API uygulamasını kullanır .


2
Yakın, ama bir JSONArray için bir doğrulama eksik (ben bu yazı daha uygun bir işlev ile güncelledim)
Arthur

9
"{'Merhaba': 'foo'} 'geçersiz'" ({} dışında 'geçersiz' eklendi) gibi bir json dizesi denedim ve JSONObject ParseException atıyor. Org.json.JSONObject kullanıyorum. Bu bekleniyor mu?
Soichi Hayashi

16
JSONObject olan kütüphaneden bahsetmedin, standart java
lib'de

6
Bu çözüm çoğu durumda çalışır, ancak bazı durumlarda başarısız olabilir. Örneğin, aslında bir sözdizimi hatası olan virgül kapanış ayından hemen önce izin verir. Diğer köşe vakaları için json.org/javadoc/org/json/JSONObject.html adresine bakın .
Hua2308

9
Posterlerin neden kod snippet'leri ile içe aktarma ifadeleri eklemek için rahatsız edilemez anlayamıyorum. Burada önemli. Buradaki ikinci derece cevap çok daha iyi.
seansand

100

JACKSON Kütüphanesi

Bir seçenek Jackson kütüphanesini kullanmak olabilir . İlk olarak en son sürümü içe aktarın (şimdi):

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

Ardından, doğru yanıtı aşağıdaki gibi uygulayabilirsiniz :

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 seçeneği

Başka bir seçenek de Google Gson'u kullanmaktır . Bağımlılığı içe aktarın:

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

Yine, önerilen çözümü şu şekilde uygulayabilirsiniz:

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

Basit bir test burada yapılır:

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

Lütfen, sürümde düzeltilecek virgül nedeniyle "küçük" bir sorun olabileceğini gözlemleyin 3.0.0.


Bu, eşleşmeyen teklifler veya eksik parantezler gibi büyük şeyler için çalışırken, Gson mutlu bir şekilde virgül içeren bir json dizisini ayrıştıracak ve RFC-4627
eurythmia

@eurythmia Doğru! 3.0 sürümünde sorunu
çözmeleri

1
Bu da {key: value} değerini doğrular, ancak geçerli bir json değildir
Pratapi Hemant Patel

2
JACKSON tuzağı: new ObjectMapper().readTree("28xjRBuOQqupRopHeSuhRQ")IntNode (28) olarak Exception olmadan ayrışır. Gerçekten beklenmiyor ...
mgaert

1
Anladığım kadarıyla bu çözümü sadece doğrulamakla kalmıyor, aynı zamanda tüm json'u da ayrıştırıyor (ve saklıyor). Sayıları Tamsayı / Uzun / Çift vb. Dönüştürür. Bu sadece sözdizimi kontrolünden daha fazlasıdır, bütün json'u hafızada saklar. Bu yoğun yükler için önemli olabilir. Sözdizimi kontrolü için daha iyi bir çözüm varsa?
javapowered

15

Google Gson ile JsonParser'ı kullanabilirsiniz:

import com.google.gson.JsonParser;

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

3
Unutmayın ki bu, dizelenmemiş dizelerde ala "asdf" hatası vermez
Andrew

1
JSON dizilerindeki virgülleri de reddetmez.
Sotirios Delimanolis

Gerçekten güvenemiyorum ... "Kaydet" dizesinin ayrıştırılabilir olduğunu söylüyor.
Dherik

Burada gson örneğinin hala birçok sapmaya izin veren yumuşak ayrıştırma modunu kullandığına dikkat edin . Diğer yanıtlarımda testcase ve katı ayrıştırma örneğiyle daha fazla ayrıntı görün .
Vadzim

14

JSONUtils kitaplığında bulunan .mayBeJSON (String str) kullanabilirsiniz .


evet ... bu işe yarıyor. Teşekkürler npinti. gson ile çalışıyordu ama orada böyle bir yöntem gördüm.
sappu

@sappu: Bu cevap sorunuzu çözdüyse işaretleyin. Çoğu kütüphane bir Dize alıp ayrıştırmayı dener, ayrıştırma başarısız olursa, yani dize geçerli bir JSON dizesi değilse, bir istisna atar.
npinti

@npinti: Ekstra başarısız oldu}. Ekstra braketli geçersiz dize için true değerini döndürür =>}
Vivek

3
Bu yöntem, kelimenin tam anlamıyla yalnızca dizenin tırnak veya köşeli parantezle başlayıp bittiğini denetler. Çok güvenilmez.
Michael Munsey

2
bu yüzden yöntem adı 'belki', 'değil' :)
Khoa

5

Doğrulama işleminizle neyi kanıtlamaya çalıştığınıza bağlıdır. Json'un diğerlerinin önerdiği gibi ayrıştırılması kesinlikle regexes kullanmaktan daha iyidir, çünkü json gramer sadece regexes ile temsil edilebileceğinden daha karmaşıktır.

Json yalnızca java kodunuz tarafından ayrıştırılırsa, doğrulamak için aynı ayrıştırıcıyı kullanın.

Ancak sadece ayrıştırma işlemi, diğer ortamlarda kabul edilip edilmeyeceğini size söylemeyecektir. Örneğin

  • birçok ayrıştırıcı, bir nesne veya dizideki virgülleri yok sayar, ancak eski IE sürümleri bir virgülle karşılaştıklarında başarısız olabilir.
  • Diğer ayrıştırıcılar sondaki virgülleri kabul edebilir, ancak arkasından tanımsız / boş giriş ekleyebilir.
  • Bazı ayrıştırıcılar alıntılanmamış özellik adlarına izin verebilir.
  • Bazı ayrıştırıcılar, dizelerdeki ASCII olmayan karakterlere farklı tepki verebilir.

Doğrulamanızın çok kapsamlı olması gerekiyorsa, şunları yapabilirsiniz:


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

Lütfen stringtree-json kütüphanesini indirin


Yukarıdaki gibi bir String tanımlamak mümkün mü? Ya da sadece Fikir için.
Santron Manibharathi

mümkün değil, bu benim hatamdan kaynaklandı. düzeltildi.Teşekkürler
Jamsheer

1
JSONValidatingReader , Java API'nın bir parçası değildir
IgorGanapolsky

Lütfen yukarıda belirtilen kütüphaneyi kullanın, Teşekkürler
Jamsheer

2

Ayrıştırma hakkında biraz:

Json ve aslında tüm diller, ikame olarak kullanılabilecek bir dizi kural olan bir gramer kullanır . json'ı ayrıştırmak için temel olarak bu ikameleri tersine çevirmeniz gerekir.

Json bir olduğu bağlam serbest dilbilgisi size sonsuz nesneler / diziler iç içe geçmiş olabilir ve json hala geçerli olacağını, yani. regex yalnızca düzenli gramerleri (dolayısıyla addaki 'reg') işler ; bu, sonsuz yuvalamaya izin vermeyen bağlamsız gramerlerin bir alt kümesidir, bu nedenle tüm geçerli json'ları ayrıştırmak için sadece regex'i kullanmak imkansızdır. 100 seviyeli derinlikte kimsenin geçmişte iç içe geçmeyeceği varsayımıyla karmaşık bir regex ve döngüler seti kullanabilirsiniz, ancak yine de çok zor olacaktır.

kendi ayrıştırıcınızı yazmaya
hazırsanız, dilbilgisi üzerinde çalıştıktan sonra yinelemeli bir iniş ayrıştırıcısı yapabilirsiniz


2

Belirli bir dizenin Kotlin'de geçerli JSON olup olmadığını kontrol edin . MByD Java'nın cevabını Kotlin'e çevirdim

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

1

Burada bir JSON dosyasını doğrulayabilen bir araç bulabilirsiniz veya JSON dosyanızı herhangi bir JSON kütüphanesi ile serisini kaldırabilirsiniz ve işlem başarılı olursa geçerli olmalıdır ( örneğin google-json , örneğin giriş ayrıştırma geçerli değil JSON).


1

Playframework 2.6'yı kullanarak, java api'de bulunan Json kütüphanesi, dizeyi ayrıştırmak için de kullanılabilir. Dize, json dizisinin bir json öğesi olabilir. Döndürülen değer burada önemli olmadığından, dizenin doğru bir json dizesi olup olmadığını belirlemek için ayrıştırma hatasını yakalarız.

    import play.libs.Json;

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

1

IMHO, en şık yol JSR 374'e uygun JavaEE standartlarından biri olan JSON İşleme için Java API'sini (JSON-P) kullanmaktır .

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'i kullanarak JSON-P'ye bağımlılığı ekleyin:

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

Daha fazla bilgi için JSON-P resmi sayfasını ziyaret edin .



1

Gördüğünüz gibi, birçok çözüm var, esas olarak kontrol etmek için JSON'u ayrıştırıyor ve sonunda emin olmak için ayrıştırmanız gerekecek.

Ancak, bağlama bağlı olarak, bir ön kontrol ile performansları artırabilirsiniz.

API'ları çağırdığımda yaptığım şey, sadece ilk karakterin '{' ve sonuncusunun '}' olduğunu kontrol etmektir. Durum böyle değilse, ayrıştırıcı oluşturma zahmetine girmem.


0

Bunun için çok basit bir çözüm buldum.

Lütfen önce bu kütüphaneyi yükleyin 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
    }

Bitti. Zevk almak


0

Cevaplar kısmen doğrudur. Aynı problemle de karşılaştım. Json ayrıştırma ve istisna kontrol normal yol gibi görünüyor ama çözüm giriş json için başarısız bir şey gibi

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

Gördüğünüz gibi json geçersiz çünkü sondaki çöp karakterler var. Ancak, yukarıdaki json'u jackson veya gson kullanarak ayrıştırmaya çalışırsanız, geçerli json'un ayrıştırılmış haritasını alırsınız ve çöp sondaki karakterler göz ardı edilir. Json geçerliliğini kontrol etmek için ayrıştırıcıyı kullanırken gerekli çözüm değildir.

Bu sorunun çözümü için buraya bakın .

Not: Bu soru bana sorularak cevaplandı.


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

ve sonra JSON String'inizde geçen bu işlevi çağırı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.");
        }
    }
}

Yukarıdaki çözüm her iki senaryoyu da kapsar:

  • yinelenen anahtar
  • eşleşmeyen tırnak işaretleri veya eksik parantezler vb.

0

javax.jsonKütüphaneyi kullanan bir çözüm :

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

Sen kullanabilirsiniz WellFormedJsongelen sınıf Validol bildirim doğrulama kütüphanesine.

Bildirgenin kendisi aşağıdaki gibi görünebilir:

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

Kontrol aşaması şöyle görünür:

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

Bu kadar basit bir görev için aşırıya kaçmış gibi görünebilir, ancak karmaşık bir isteği doğrulamanız gerektiğinde parlar. Geçerli olanın hızlı başlangıç ​​bölümüne göz atın .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.