How do I validate a JSON string in Java? Or could I parse it using regular expressions?
A wild idea, try parsing it and catch the exception:
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;
}
This code uses org.json JSON API implementation that is available on github, in maven and partially on Android.
JACKSON Library
One option would be to use Jackson library. First import the latest version (now is):
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.7.0</version>
</dependency>
Then, you can implement the correct answer as follows:
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 option
Another option is to use Google Gson. Import the dependency:
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.5</version>
</dependency>
Again, you can implement the proposed solution as:
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 simple test follows here:
//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
Please, observe that there could be a "minor" issue due to trailing commas that will be fixed in release 3.0.0.
With Google Gson you can use JsonParser:
import com.google.gson.JsonParser;
JsonParser parser = new JsonParser();
parser.parse(json_string); // throws JsonSyntaxException
You could use the .mayBeJSON(String str) available in the JSONUtils library.
It depends on what you are trying to prove with your validation.
Certainly parsing the json as others have suggested is better than using regexes, because the grammar of json is more complicated than can be represented with just regexes.
If the json will only ever be parsed by your java code, then use the same parser to validate it.
But just parsing won't necessarily tell you if it will be accepted in other environments. e.g.
many parsers ignore trailing commas in an object or array, but old versions of IE can fail when they hit a trailing comma.
Other parsers may accept a trailing comma, but add an undefined/null entry after it.
Some parsers may allow unquoted property names.
Some parsers may react differently to non-ASCII characters in strings.
If your validation needs to be very thorough, you could:
try different parsers until you find one that fails on all the corner cases I mentioned above
or you could probably run jsonlint using javax.script.*,
http://npmjs.org/package/jsonlint
or combine using a parser with running jshint using javax.script.*.
https://www.npmjs.org/package/jshint
https://github.com/webjars/jshint
A bit about parsing:
Json, and in fact all languages, use a grammar which is a set of rules that can be used as substitutions. in order to parse json, you need to basically work out those substitutions in reverse
Json is a context free grammar, meaning you can have infinitely nested objects/arrays and the json would still be valid. regex only handles regular grammars (hence the 'reg' in the name), which is a subset of context free grammars that doesn't allow infinite nesting, so it's impossible to use only regex to parse all valid json. you could use a complicated set of regex's and loops with the assumption that nobody will nest past say, 100 levels deep, but it would still be very difficult.
if you ARE up for writing your own parser
you could make a recursive descent parser after you work out the grammar
String jsonInput = "{\"mob no\":\"9846716175\"}";//Read input Here
JSONReader reader = new JSONValidatingReader();
Object result = reader.read(jsonInput);
System.out.println("Validation Success !!");
Please download stringtree-json library
Here is a working example for strict json parsing with gson library:
public static JsonElement parseStrict(String json) {
// throws on almost any non-valid json
return new Gson().getAdapter(JsonElement.class).fromJson(json);
}
See also my other detailed answer in How to check if JSON is valid in Java using GSON with more info and extended test case with various non-valid examples.
The answers are partially correct. I also faced the same problem. Parsing the json and checking for exception seems the usual way but the solution fails for the input json something like
{"outputValueSchemaFormat": "","sortByIndexInRecord": 0,"sortOrder":847874874387209"descending"}kajhfsadkjh
As you can see the json is invalid as there are trailing garbage characters. But if you try to parse the above json using jackson or gson then you will get the parsed map of the valid json and garbage trailing characters are ignored. Which is not the required solution when you are using the parser for checking json validity.
For solution to this problem see here.
PS: This question was asked and answered by me.
Check whether a given string is valid JSON in Kotlin. I Converted answer of MByD Java to Kotlin
fun isJSONValid(test: String): Boolean {
try {
JSONObject(test);
} catch (ex: JSONException) {
try {
JSONArray(test);
} catch (ex1: JSONException) {
return false;
}
}
return true;
}
A solution using the javax.json library:
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;
}
As you can see, there is a lot of solutions, they mainly parse the JSON to check it and at the end you will have to parse it to be sure.
But, depending on the context, you may improve the performances with a pre-check.
What I do when I call APIs, is just checking that the first character is '{' and the last is '}'. If it's not the case, I don't bother creating a parser.
Here you can find a tool that can validate a JSON file, or you could just deserialize your JSON file with any JSON library and if the operation is successful then it should be valid (google-json for example that will throw an exception if the input it is parsing is not valid JSON).
Using Playframework 2.6, the Json library found in the java api can also be used to simply parse the string. The string can either be a json element of json array. Since the returned value is not of importance here we just catch the parse error to determine that the string is a correct json string or not.
import play.libs.Json;
public static Boolean isValidJson(String value) {
try{
Json.parse(value);
return true;
} catch(final Exception e){
return false;
}
}
IMHO, the most elegant way is using the Java API for JSON Processing (JSON-P), one of the JavaEE standards that conforms to the 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();
}
Using Maven, add the dependency on JSON-P:
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.json</artifactId>
<version>1.1.4</version>
</dependency>
Visit the JSON-P official page for more informations.
in Gson Version
try {
String errorBody = response.errorBody().string();
MyErrorResponse errorResponse = new Gson().fromJson(errorBody, MyErrorResponse.class);
} catch (JsonSyntaxException e) {
e.printStackTrace();
}
I have found a very simple solution for it.
Please first install this library net.sf.json-lib for it.
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
}
Done. Enjoy
import static net.minidev.json.JSONValue.isValidJson;
and then call this function passing in your JSON String :)
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.");
}
}
}
Above solution covers both the scenarios:
duplicate key
mismatched quotes or missing parentheses etc.
You can try below code, worked for me:
import org.json.JSONObject;
import org.json.JSONTokener;
public static JSONObject parseJsonObject(String substring)
{
return new JSONObject(new JSONTokener(substring));
}
Related
I call a post API which responds with details on specific addresses, however some of the responses that get returned have no data so they'll be returned as null. How do I stop the casting error in my code?
I currently only get the data as a Json Object and I'm not sure how to rework my code that so when a JsonNull Element gets returned I can handle that data.
JsonElement element = new JsonParser().parse(jsonString);
JsonObject jsonObject = element.getAsJsonObject();
jsonObject = jsonObject.getAsJsonObject("response"); // This is either an object or it is null
String buildName = jsonObject.get("buildingName").getAsString();
String buildNum = jsonObject.get("premisesNumber").getAsString();
String streetName = jsonObject.get("streetName").getAsString();
What I expect to be returned would be either the address details for valid addresses or no information at all for the invalid addresses.
The error that gets produced is this:
java.lang.ClassCastException: com.google.gson.JsonNull cannot be cast to com.google.gson.JsonObject
Before getAsString() check for isJsonNull(). It'll return true if object is Null.
You can rewrite your code as below
String buildName= (jsonObject.get("buildingName").isJsonNull ? null : jsonObject.get("buildingName").getAsString());
Normally is a good idea validate the data is JSON valid
public static boolean isJSONValid(String test) {
try {
new JSONObject(test);
} catch (JSONException ex) {
try {
new JSONArray(test);
} catch (JSONException ex1) {
return false;
}
}
return true;
}
Function above will return you true in case the string is a valid JSON object(could be an object or an array of objects).
After that you can continue parsing using Jackson lib or the GSON lib
I have some JSON content in bytebuffer as : {\"ID\":101}"}
This content is being returned from a service invocation. I get result from that microservice in a bytebuffer. (This means - I cannot get the content changed)
Now, I need to get the json object from this buffer. I'm using this code :
ByteBuffer payloadByteBuffer = invokeResult.getPayload();
byte[] payloadByteArray = payloadByteBuffer.array();
rawJson = new String(payloadByteArray, Charset.forName("UTF-8"));
System.out.println("Raw JSon result = "+rawJson);
The string that gets printed is : "{\"ID\":101}"
Please note that '\' is getting printed within the string but it is originally used to escape double quote. So, when I try to convert this string to JSON object, I get an error :
"Missing value at 1 [character 2 line 1]"
which is probably due to '\' not being used to escape double quote character(I think).
So, My question is, how do I modify my string to treat '\' character for it's correct purpose?
I have tried replacing "\". but it didn't work. I don't know why.
I have also tried different charset encoding : US-ASCII and ASCII but got the same result.
You can try json-simple. You can use the dependency from here
P.S: Your JSON response is wrong.
ByteBuffer payloadByteBuffer = invokeResult.getPayload();
byte[] payloadByteArray = payloadByteBuffer.array();
rawJson = new String(payloadByteArray, Charset.forName("UTF-8"));
JSONParser parser = new JSONParser();
try {
JSONObject json = (JSONObject) parser.parse(rawJson);
} catch (ParseException e) {
e.printStackTrace();
}
It parses the JSON with \ in it.
How about using the apache's commons lang library?
I think it's a simple and easy way of remove your problem away.
Here is my full test code for you.
package just.test;
import java.nio.charset.Charset;
import org.apache.commons.lang3.StringEscapeUtils;
import org.json.JSONObject;
import com.ibm.icu.impl.ByteBuffer;
public class UnescapeCharTest {
private static void testJSONString(final String rawJson)
{
JSONObject json = null;
try
{
json = new JSONObject(rawJson);
System.out.println("ID = "+json.get("ID"));
}
catch(org.json.JSONException je)
{
je.printStackTrace();
}
String convJson = rawJson.replace("\\", "");
try
{
json = new JSONObject(convJson);
System.out.println("ID = "+json.get("ID"));
}
catch(org.json.JSONException je)
{
je.printStackTrace();
}
convJson = StringEscapeUtils.unescapeJson(rawJson);
try
{
json = new JSONObject(convJson);
System.out.println("ID = "+json.get("ID"));
}
catch(org.json.JSONException je)
{
je.printStackTrace();
}
}
public static void main(String[] args)
{
String rawJson = "{\\\"ID\\\":101}";
testJSONString(rawJson);
String rawJson2 = null;
ByteBuffer payloadByteBuffer = ByteBuffer.wrap(rawJson.getBytes());
byte[] payloadByteArray = payloadByteBuffer.array();
rawJson2 = new String(payloadByteArray, Charset.forName("UTF-8"));
testJSONString(rawJson2);
}
}
I hope the code is right for you.
Have a good coding...
I have the below code that basically reads a bunch of JSON strings, and converts them to a java object. My problem is if at any point, the transformation fails for any of the JSON strings, it doesn't process the others strings. What I need is -
Find the string for which the error occured.
In the exception block do something to continue processing.
Here is my code to convert from JSON to Java.
public static <T> T convertToObject(String jsonString,Class<T> classType){
T obj = null;
try {
obj = objectMapper.readValue(jsonString, classType);
} catch (Exception e) {
throw new Exception("Unable to convert to DTO :" + e.getMessage(), e);
}
return obj;
}
I think you need a custom deserializer. Standard ObjectMapper will do all or nothing. Read more about creating a custom deserializer for Jackson ObjectMapper here:
http://www.baeldung.com/jackson-deserialization
I have the following json parsing code which works fine when tested as a java application. But on using it with in an android platform and running , returned the following error
"Unexpected token END OF FILE at position 0"
Here is my code
public boolean parseJSON(String content) {
boolean retvalue=false;
String jsonString=null;
JSONParser parser=new JSONParser();
Object obj;
try {
System.out.println("in the parse json");
obj = parser.parse(content);
JSONArray array=(JSONArray)obj;
JSONObject obj2=(JSONObject)array.get(0);
jsonString=(String) obj2.get("user_id");
System.out.println("in the parse json "+jsonString);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (null != jsonString) {
retvalue = true;
}
return retvalue;
}
The input string for the method is the following
[{"user_id":"1","username":"arvind","password":"somu","firstname":"Arvind somu","accountNumber":"1234567","lastname":"","address":"","email":"sample#gmail.com"}]
I have got the value 1 printed, when tried with java, but no idea why this issue is coming with android. Can body suggest what is wrong with the code.The parser I am using is json-simple1.1.1
Use this:
JSONObject obj2;
obj2 = array.optJSONObject(0);
The method optJSONObject returns a JSONObject and you dont have to cast it, where as get() returns an Object. Try this i think this may solve it.
I would like to search after a given keyword in a big JSON file. Does anybody know a java library for this?
Gson could help you to parse the json file easily.
Unlike many other JSON libraries, Gson supports streaming which means you can examine the file in small chunks.
If you're just searching for a keyword, I don't see how the fact that it's JSON requires a special library. This would only help if you were looking for something particular to JSON such as a key or value.
Couldn't you just scan the file line-by-line and search for the substring?
public static boolean find(File f, String searchString) {
boolean result = false;
Scanner in = null;
try {
in = new Scanner(new FileReader(f));
while(in.hasNextLine() && !result) {
if (in.nextLine().contains(searchString))
return true;
}
}
catch(IOException e) {
e.printStackTrace();
}
finally {
try { in.close() ; } catch(Exception e) { /* ignore */ }
}
return false;
}
from http://technojeeves.com/joomla/index.php/free/109-search-for-string-in-text-file-in-java.
You can find json library it here.
Search for JSONArray and JSONObject
http://www.json.org/javadoc/org/json/JSONArray.html
it's pretty easy to work with them.