I have written a JSON Schema by 2019-09 (https://json-schema.org/draft/2019-09/release-notes.html). How can I validate it using java?
I want to write the method (throw Exception if validation fails):
void validate(Path pathToSchema) throws Exception {
// validation of schema by pathToSchema
}
P.S. I want to validate the JSON Schema for correctness, not JSON Document by JSON Schema.
You do something like this with the well known networknt lib:
JsonSchema schema = null;
JsonSchemaFactory factory = JsonSchemaFactory.getInstance(VersionFlag.V201909);
try {
schema = factory.getSchema(
"{\n"
+ " \"$schema\": \"http://json-schema.org/draft/2019-09/schema\",\n"
+ " \"$id\": \"#MyJsonClassSchema.json\",\n"
+ " \"type\": \"object\",\n"
+ " \"properties\": {\n"
+ " \"myProperty\": {\n"
+ " \"type\": \"string\"\n"
+ " }\n"
+ " }\n"
+ "}"
);
} catch (JsonSchemaException e) {
System.out.println("json schema invalid: \n" + e);
}
return schema;
This will validate some features of the json-schema starting with the schema version you set in your input.
You can use the Json validator: - https://github.com/fge/json-schema-validator
Or you can simply try to parse the Json using Google Gson and catch syntax exception to validate it like below :-
try{
JsonParser parser = new JsonParser();
parser.parse(passed_json_string);
}
catch(JsonSyntaxException jse){
System.out.println("Not a valid Json String:"+jse.getMessage());
}
Related
I am using json library to convert json to xml but while converting I want to ignore a nested json object to be converted to xml tags.
eg.
Plane json is as :
{"id":"9568","name":"Customer Analysis","group":"demo","param":{"globalSettings":{"showLegends":false,"legendPosition":"bottom center"}}}
JSONObject json = new JSONObject("{\"id\":\"9568\",\"name\":\"Customer Analysis\",\"group\":\"demo\",\"param\":{\"globalSettings\":{\"showLegends\":false,\"legendPosition\":\"bottom center\"}}}");
String xml = XML.toString(json);
System.out.println(xml);
Now in above example, I want in xml with a json as it is inside. Whereas now various elements are created for showLegends and legendPosition inside globalSettings.
Current XML is as follows :
<name>Customer Analysis</name>
<id>9568</id>
<group>demo</group>
<param>
<globalSettings>
<showLegends>false</showLegends>
<legendPosition>bottom center</legendPosition>
</globalSettings>
</param>
Expected XML should be as follows :
<name>Customer Analysis</name>
<id>9568</id>
<group>demo</group>
<param>
<globalSettings>
{"showLegends":false,"legendPosition":"bottom center"}
</globalSettings>
</param>
How can I handle this?
I think you need to tweak JSON before converting.
Can you try this below?
String json = "{\n" +
" \"user\": \"gerry\",\n" +
" \"likes\": [1, 2, 4],\n" +
" \"followers\": {\n" +
" \"options\": {\n" +
" \"key1\": \"a\",\n" +
" \"key2\": \"b\"\n" +
" } \n" +
" }\n" +
"}";
JSONObject jsonObject = new JSONObject(json);
JSONObject followers = jsonObject.getJSONObject("followers");
String options = followers.optString("options");
followers.put("options", options);
String s = XML.toString(jsonObject);
System.out.println(XML.unescape(s));
result:
<followers><options>{"key1":"a","key2":"b"}</options></followers><user>gerry</user><likes>[1,2,4]</likes>
Extra Question:
What if I don't want options as an xml element and it should be part of json?
String json = "{\n" +
" \"user\": \"gerry\",\n" +
" \"likes\": [1, 2, 4],\n" +
" \"followers\": {\n" +
" \"options\": {\n" +
" \"key1\": \"a\",\n" +
" \"key2\": \"b\"\n" +
" } \n" +
" }\n" +
"}";
JSONObject jsonObject = new JSONObject(json);
jsonObject.put("followers", jsonObject.optString("followers"));
// org.json 20180813
String s = XML.toString(jsonObject);
System.out.println(XML.unescape(s));
result:
<followers>{"options":{"key1":"a","key2":"b"}}</followers><user>gerry</user><likes>1</likes><likes>2</likes><likes>4</likes>
You need to modify your json a bit:
String json = "{\"user\":\"gerry\",\"likes\":[1,2,4],\"followers\":{\"options\":\"{key1:a,key2:b}\"}}";
JSONObject jsonObject = new JSONObject(json);
String xml = XML.toString(jsonObject);
System.out.println(XML.unescape(xml));
note that the "options" should be as "String" (shaped like JSON), then the XML parser will treat it as a regular string.
You either need to tweak the JSON before conversion, or tweak the XML after conversion.
Since such tweaking is so often required, one approach is to do the conversion using XSLT 3.0 so you have transformation capability built-in to the tool.
Underscore-java library has static methods U.fromJson(json) and U.toXml(map). You may modify map and generate xml. I am the maintainer of the project.
Map<String, Object> map = U.fromJsonMap("{\"id\":\"9568\",\"name\":\"Customer Analysis\",\"group\":\"demo\",\"param\":{\"globalSettings\":{\"showLegends\":false,\"legendPosition\":\"bottom center\"}}}");
U.set(map, "param.globalSettings", U.toJson((Map<String, Object>) U.get(map, "param.globalSettings")));
System.out.println(U.toXml(map));
Output:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<id>9568</id>
<name>Customer Analysis</name>
<group>demo</group>
<param>
<globalSettings>{
"showLegends": false,
"legendPosition": "bottom center"
}</globalSettings>
</param>
</root>
I'm trying to parse an xml string into JSON using Jackson.
At the moment I'm using this string:
String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
" <rootNode>\n" +
" <data>\n" +
" <cityCode>R8</cityCode>\n" +
" <place>\n" +
" <code>01</code>\n" +
" </place>\n" +
" </data>\n" +
" <data>\n" +
" <cityCode>R9</cityCode>\n" +
" <place>\n" +
" <code>02</code>\n" +
" </place>\n" +
" </data>\n" +
"</rootNode>";
Here is the code I'm using:
XmlMapper xmlMapper = new XmlMapper();
JsonNode node = xmlMapper.readTree(xml);
ObjectMapper jsonMapper = new ObjectMapper();
String json = jsonMapper.writeValueAsString(node)
But the parser only seems to get one node:
{"data":{"cityCode":"R9","place":{"code":"02"}}}
How can I get all the nodes converted into JSON?
Thank you
I get it working using readValue into a List
XmlMapper xmlMapper = new XmlMapper();
List list = xmlMapper.readValue(xml, List.class);
ObjectMapper jsonMapper = new ObjectMapper();
String json = jsonMapper.writeValueAsString(list);
Not sure why your version does not work, there seem to be issues with readTree and repeated attributes. See this article, point 5.1. Limitations
I am trying to implement a function to be able to remove or modify a json object base on a specified json path. For example, if i have a below json string/object:
{
"PersonalDetailsDTO": {
"FirstName": "Mark",
"LastName": "Sully",
"TotalDependent": "2",
"DOB": "19811212",
"SecQuestion": "Some Que",
"SecAnswer": "Some-Ans",
"Mobile": "0123456789",
"Email": "some#validemail.com",
"Title": "Mr",
"EmploymentListDTO": [
{
"Type": "Full-time",
"Probation": true
}
],
"AddressListDTO": [
{
"AddressType": "BUS",
"PostCode": "1234",
"State": "NSW",
"StreetName": "miller",
"StreetNumber": "111",
"StreetType": "Invalid",
"Suburb": "Sydney",
"UnitNumber": "Maximum"
}
]
}
}
And i want to remove element $.PersonalDetailsDTO.AddressListDTO.PostCode.
I've done quite some search, and the one lib i found is JsonPath: http://static.javadoc.io/com.jayway.jsonpath/json-path/2.2.0/com/jayway/jsonpath/JsonPath.html
So i wrote the below code:
public static void main(String[] args) {
// Prints "Hello, World" to the terminal window.
String jsonString = "{\n" +
" \"PersonalDetailsDTO\": {\n" +
" \"FirstName\":\"Mark\",\n" +
" \"LastName\":\"Sully\",\n" +
" \"Title\":\"Mr\",\n" +
" \"DOB\":\"19811201\",\n" +
" \"SecQuestion\":\"Some Ques\",\n" +
" \"SecAnswer\":\"Some-Ans\",\n" +
" \"Email\":\"some#validemail.com\",\n" +
" \"EmploymentListDTO\": [\n" +
" {\n" +
" \"Type\": \"Full-time\",\n" +
" \"Probation\": true\n" +
" }\n" +
" ],\n" +
" \"AddressListDTO\": [\n" +
" {\n" +
" \"AddressType\": \"Residential\",\n" +
" \"PostCode\": \"2345\",\n" +
" \"State\": \"NSW\",\n" +
" \"StreetName\": \"MEL\",\n" +
" \"StreetNumber\": \"2\",\n" +
" \"StreetType\": \"Boulevard\",\n" +
" \"Suburb\": \"Melbourne\",\n" +
" \"UnitNumber\": \"345\"\n" +
" }\n" +
" ]\n" +
" } \n" +
"}";
JSONObject jsonObject = new JSONObject(jsonString);
System.out.println("Before: " + jsonObject.toString());
JsonPath jp = JsonPath.compile("$.PersonalDetailsDTO.AddressListDTO[0].PostCode");
Configuration conf = Configuration.defaultConfiguration();
Object json = conf.jsonProvider().parse(jsonString);
System.out.println("After: " + jp.delete(json, conf).toString());
}
And the console log displays:
Before: {"PersonalDetailsDTO":{"EmploymentListDTO":[{"Type":"Full-time","Probation":true}],"SecAnswer":"Some-Ans","Email":"some#validemail.com","SecQuestion":"Some Ques","FirstName":"Mark","DOB":"19811201","AddressListDTO":[{"StreetName":"MEL","Suburb":"Melbourne","State":"NSW","StreetNumber":"2","UnitNumber":"345","AddressType":"Residential","PostCode":"2345","StreetType":"Boulevard"}],"Title":"Mr","LastName":"Sully"}}
After: {PersonalDetailsDTO={FirstName=Mark, LastName=Sully, Title=Mr, DOB=19811201, SecQuestion=Some Ques, SecAnswer=Some-Ans, Email=some#validemail.com, EmploymentListDTO=[{"Type":"Full-time","Probation":true}], AddressListDTO=[{"AddressType":"Residential","State":"NSW","StreetName":"MEL","StreetNumber":"2","StreetType":"Boulevard","Suburb":"Melbourne","UnitNumber":"345"}]}}
Looks like JsonPath is doing it's job and removing $.PersonalDetailsDTO.AddressListDTO.PostCode. However, there's something very obvious that bothers me:
Looking at the json string produced by .toString() in before and after case, JSONObject API printed a nice string in true json standard format with every double quotes "" present, while the JsonPath .toString produce a customer string format that has some elements in double quote "" while others are not and i can not use it further like JSONObject.
And what i noticed is that although JsonPath claim to accept "java.lang.Object" as parameter in many of its function, what it truely accept is something called "jsonProvider". Not sure if it's causing the weird .toString() behavior.
Anyway, does anyone know how get a nice formatted json string out of JsonPath APIs like remove(), put(), read() and many other? Or to convert the return value to something like JSONObject?
If you know any other Java lib that can do remove/modify element by json path, please feel free to recommand. Thank you!
I don't know JsonPath.
I think you should use jackson which is defacto standard lib when work with JSON in java
aproximate what you are going to do is:
String jsonString = "{"k1": {"k2":"v2"}";
ObjectMapper mapper = new ObjectMapper();
JsonNode actualObj = mapper.readTree(jsonString);
actualObj.at("/k1/k2").getValueAsInt()
and replace getValueAsInt with any other function
I have seen many examples, but none of them are not like what i want.
Consider I have a JSONObject like:
[ {
"id" : "572add95e4b0b04f4d502a3c",
"amount" : 109.27,
"sourceCurrency" : "MXN",
"targetCurrency" : "USD",
"recipientBankId" : "572add95e4b0b04f4d502a37",
"iban" : "5805742027",
"created" : "2016-05-05T05:43:49.194"
}, {
"id" : "572add95e4b0b04f4d502a3e",
"amount" : 722.41,
"sourceCurrency" : "GBP",
"targetCurrency" : "INR",
"recipientBankId" : "572add95e4b0b04f4d502a32",
"iban" : "4688276585",
"created" : "2016-05-05T05:43:49.2"
}]
and i want to access to the second json and iban value.
How can i do it?
With your json content
String json = "[ {\n" +
" \"id\" : \"572add95e4b0b04f4d502a3c\",\n" +
" \"amount\" : 109.27,\n" +
" \"sourceCurrency\" : \"MXN\",\n" +
" \"targetCurrency\" : \"USD\",\n" +
" \"recipientBankId\" : \"572add95e4b0b04f4d502a37\",\n" +
" \"iban\" : \"5805742027\",\n" +
" \"created\" : \"2016-05-05T05:43:49.194\"\n" +
"}, {\n" +
" \"id\" : \"572add95e4b0b04f4d502a3e\",\n" +
" \"amount\" : 722.41,\n" +
" \"sourceCurrency\" : \"GBP\",\n" +
" \"targetCurrency\" : \"INR\",\n" +
" \"recipientBankId\" : \"572add95e4b0b04f4d502a32\",\n" +
" \"iban\" : \"4688276585\",\n" +
" \"created\" : \"2016-05-05T05:43:49.2\"\n" +
"}]";
You first need to get a JSONArray from your json content :
JSONArray array = new JSONArray(json);
Then you read the second ( at the index 1 ) JSONObject within the array:
JSONObject o = array.getJSONObject(1);
And finally you read the iban from the JSONObject :
String secondIban = o.getString("iban");
System.out.println(secondIban);
With of course all this surrounded with a try/catch to catch JSONException:
try {
JSONArray array = new JSONArray(json);
JSONObject o = array.getJSONObject(1);
String secondIban = o.getString("iban");
System.out.println(secondIban);
}catch(JSONException jse){
jse.printStackTrace();
}
Note
If you want to be aware that the iban field doesn't exist use o.getString("iban").
A JSONException will be thrown if the field is missing.
If you are okay to work with an empty string "" as default value for the eventually missing field then use o.optString("iban") to read the field.
you can do something like below.
public static void main(String[] args) {
String json = "[{\n" +
" \"id\" : \"572add95e4b0b04f4d502a3c\",\n" +
" \"amount\" : 109.27,\n" +
" \"sourceCurrency\" : \"MXN\",\n" +
" \"targetCurrency\" : \"USD\",\n" +
" \"recipientBankId\" : \"572add95e4b0b04f4d502a37\",\n" +
" \"iban\" : \"5805742027\",\n" +
" \"created\" : \"2016-05-05T05:43:49.194\"\n" +
"}, {\n" +
" \"id\" : \"572add95e4b0b04f4d502a3e\",\n" +
" \"amount\" : 722.41,\n" +
" \"sourceCurrency\" : \"GBP\",\n" +
" \"targetCurrency\" : \"INR\",\n" +
" \"recipientBankId\" : \"572add95e4b0b04f4d502a32\",\n" +
" \"iban\" : \"4688276585\",\n" +
" \"created\" : \"2016-05-05T05:43:49.2\"\n" +
"}]";
JSONArray objects = new JSONArray(json);
System.out.println(((JSONObject)objects.get(1)).get("iban"));
}
Use optString instead getString.
optString - Will return blank string if element/key not found in JSON.
getString - Will throw an exception.
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
================================
public static void main(String[] args) throws JSONException {
String str = "[{\"id\":\"572add95e4b0b04f4d502a3c\",\"amount\":109.27,\"sourceCurrency\":\"MXN\",\"targetCurrency\":\"USD\",\"recipientBankId\":\"572add95e4b0b04f4d502a37\",\"iban\":\"5805742027\",\"created\":\"2016-05-05T05:43:49.194\"},{\"id\":\"572add95e4b0b04f4d502a3e\",\"amount\":722.41,\"sourceCurrency\":\"GBP\",\"targetCurrency\":\"INR\",\"recipientBankId\":\"572add95e4b0b04f4d502a32\",\"iban\":\"4688276585\",\"created\":\"2016-05-05T05:43:49.2\"}]";
JSONArray jsonArray = new JSONArray(str);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject = jsonArray.optJSONObject(i);
/* optString - will return blank string if element not found */
String iban = jsonObject.optString("iban");
System.out.println(iban);
}
}
What you should do is transform string into json:
public JsonObject parseJsonString(String jsonString) {
JsonParser jsonParser = new JsonParser();
JsonObject jsonObject = (JsonObject) jsonParser.parse(jsonString);
return jsonObject;
}
then extract values that you are after:
final String iban = jsonObject.get("iban").getAsString();
To read a value from JSON you can only with the next methods:
Data bind
Tree Model
Streaming API
XPath like
Which method to use is up to you because all methods have advantage and disadvantage.
Engines:
Fastjson supports Data bind, XPath like
Gson supports Data bind, Tree Model, Streaming API
Jackson supports Data bind, Tree Model, Streaming API
JsonPath supports XPath like
Genson supports Data bind, Tree model with Jsonp, Streaming API
Ig json parser supports Data bind
Moshi supports Data bind
JSON java supports Tree Model
LoganSquare supports Data bind
I guess you want to select only a part from json, so xpath like could be your choice with syntax like this $[1].iban (JsonPath)
I want some help to find a quick solution for my problem. Given a json object that is large with a recursive model. I want to list the JSON sub elements & its immediate parent Object( only the sub object which satisfies the given key value condition).
Ex :
{
Object : {
id : "0001",
parent:"A",
child: {
id:"0001A",
Country:"US",
parent:"B",
child:{
id:"0001AA",
Country:"UK",
parent:"C",
child:{
id:"0000AAA",
Country:"US",
parent:"D",
child:{
.........
}
}
}
}
}
}
I want to list the id's of the subObject whose country is 'US' and it's parent id..
is there available any readymade plugins to handle these kind of scenarios in JAVA , without using object mappers/custom class objects..
Ps provide any possible idea ..
Yes, it is possible write code using the Jackson Tree Model API which would traverse a JSON tree and select the nodes that satisfy criteria. Here is an example:
public class JacksonTree2 {
public static final String JSON = "{\"Ex\" : {\"Object\" : {\n" +
" \"id\" : \"0001\",\n" +
" \"parent\":\"A\",\n" +
" \"child\": {\n" +
" \"id\":\"0001A\",\n" +
" \"Country\":\"US\",\n" +
" \"parent\":\"B\",\n" +
" \"child\":{\n" +
" \"id\":\"0001AA\",\n" +
" \"Country\":\"UK\",\n" +
" \"parent\":\"C\",\n" +
" \"child\":{\n" +
" \"id\":\"0000AAA\",\n" +
" \"Country\":\"US\",\n" +
" \"parent\":\"D\",\n" +
" \"child\":{\n" +
" \n" +
" }\n" +
" }\n" +
" }\n" +
"\t}\n" +
"}}}";
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
JsonNode root = mapper.readTree(JSON);
for (JsonNode node : root.findParents("Country")) {
if ("UK".equals(node.get("Country").asText())) {
System.out.println(node.get("id"));
break;
}
}
}
}
Output:
"0001AA"