Is there a stable library that can validate JSON against a schema?
I found a couple hits on google:
- From the Chromium project: http://aaronboodman-com-v1.blogspot.com/2010/11/c-version-of-json-schema.html
- http://avro.apache.org/docs/1.4.1/api/cpp/html/index.html
You could also plug a Python or Javascript interpreter into your app, and simply run the native version of those validator implementations that you've already found.
Is there a reason I can't easily find a C++ JSON schema validator?
I believe JSON originated as a web technology, and C/C++ has fallen out of favor for web app implementation.
Answer from Merlyn Morgan-Graham on Stack OverflowIs there a stable library that can validate JSON against a schema?
I found a couple hits on google:
- From the Chromium project: http://aaronboodman-com-v1.blogspot.com/2010/11/c-version-of-json-schema.html
- http://avro.apache.org/docs/1.4.1/api/cpp/html/index.html
You could also plug a Python or Javascript interpreter into your app, and simply run the native version of those validator implementations that you've already found.
Is there a reason I can't easily find a C++ JSON schema validator?
I believe JSON originated as a web technology, and C/C++ has fallen out of favor for web app implementation.
Valijson is a very good library which depends only on Boost (And I'm actually hoping to change that). It doesn't even depend on any particular JSON parser, providing adapters for most commonly-used libraries like JsonCpp, rapidjson and json11.
The code may seem verbose, but you can always write a helper (example for JsonCpp):
#include <json-cpp/json.h>
#include <sstream>
#include <valijson/adapters/jsoncpp_adapter.hpp>
#include <valijson/schema.hpp>
#include <valijson/schema_parser.hpp>
#include <valijson/validation_results.hpp>
#include <valijson/validator.hpp>
void validate_json(Json::Value const& root, std::string const& schema_str)
{
using valijson::Schema;
using valijson::SchemaParser;
using valijson::Validator;
using valijson::ValidationResults;
using valijson::adapters::JsonCppAdapter;
Json::Value schema_js;
{
Json::Reader reader;
std::stringstream schema_stream(schema_str);
if (!reader.parse(schema_stream, schema_js, false))
throw std::runtime_error("Unable to parse the embedded schema: "
+ reader.getFormatedErrorMessages());
}
JsonCppAdapter doc(root);
JsonCppAdapter schema_doc(schema_js);
SchemaParser parser(SchemaParser::kDraft4);
Schema schema;
parser.populateSchema(schema_doc, schema);
Validator validator(schema);
validator.setStrict(false);
ValidationResults results;
if (!validator.validate(doc, &results))
{
std::stringstream err_oss;
err_oss << "Validation failed." << std::endl;
ValidationResults::Error error;
int error_num = 1;
while (results.popError(error))
{
std::string context;
std::vector<std::string>::iterator itr = error.context.begin();
for (; itr != error.context.end(); itr++)
context += *itr;
err_oss << "Error #" << error_num << std::endl
<< " context: " << context << std::endl
<< " desc: " << error.description << std::endl;
++error_num;
}
throw std::runtime_error(err_oss.str());
}
}
Videos
I think that you just need to add
'additionalProperties': false
to your schema. This will stop unknown properties being provided.
So now your results will be:- True, False, False
test code....
void Main()
{
var schema = JsonSchema.Parse(
@"{
'type': 'object',
'properties': {
'name': {'type':'string'},
'hobbies': {'type': 'array'}
},
'additionalProperties': false
}");
IsValid(JObject.Parse(
@"{
'name': 'James',
'hobbies': ['.NET', 'LOLCATS']
}"),
schema).Dump();
IsValid(JObject.Parse(
@"{
'surname': 2,
'hobbies': ['.NET', 'LOLCATS']
}"),
schema).Dump();
IsValid(JObject.Parse(
@"{
'name': 2,
'hobbies': ['.NET', 'LOLCATS']
}"),
schema).Dump();
}
public bool IsValid(JObject obj, JsonSchema schema)
{
return obj.IsValid(schema);
}
output :-
True
False
False
You could also add "required":true to the fields that must be supplied that way you can return a message with details of missing/invalid fields:-
Property 'surname' has not been defined and the schema does not allow additional properties. Line 2, position 19.
Required properties are missing from object: name.
Invalid type. Expected String but got Integer. Line 2, position 18.
Ok i hope this will help.
This is your schema:
public class test
{
public string Name { get; set; }
public string ID { get; set; }
}
This is your validator:
/// <summary>
/// extension that validates if Json string is copmplient to TSchema.
/// </summary>
/// <typeparam name="TSchema">schema</typeparam>
/// <param name="value">json string</param>
/// <returns>is valid?</returns>
public static bool IsJsonValid<TSchema>(this string value)
where TSchema : new()
{
bool res = true;
//this is a .net object look for it in msdn
JavaScriptSerializer ser = new JavaScriptSerializer();
//first serialize the string to object.
var obj = ser.Deserialize<TSchema>(value);
//get all properties of schema object
var properties = typeof(TSchema).GetProperties();
//iterate on all properties and test.
foreach (PropertyInfo info in properties)
{
// i went on if null value then json string isnt schema complient but you can do what ever test you like her.
var valueOfProp = obj.GetType().GetProperty(info.Name).GetValue(obj, null);
if (valueOfProp == null)
res = false;
}
return res;
}
And how to use is:
string json = "{Name:'blabla',ID:'1'}";
bool res = json.IsJsonValid<test>();
If you have any question please ask, hope this helps, please take into consideration that this isn't a complete code without exception handling and such...
There is Json.NET Schema for performing validation.
Hi @DEEPAK KUMPALA ,
You can use Deserialize subsections of a JSON payload to finish it.
I test it under. Net6.0.
Below is the code:
using System.Collections.Generic;
using System;
using System.Text.Json;
namespace DeserializeExtra
{
public class Rootobject
{
public int pageNumber { get; set; }
public int pageSize { get; set; }
public Datum[] data { get; set; }
}
public class Datum
{
public string Id { get; set; }
public DateTime LastModified { get; set; }
public bool IsActive { get; set; }
public Device[] Devices { get; set; }
}
public class Device
{
public string Id { get; set; }
public bool IsActive { get; set; }
public string SerialNumber { get; set; }
}
public class Program
{
public static void Main()
{
string jsonString =
@" {
""pageNumber"": 1,
""pageSize"": 250,
""data"": [{
""Id"": ""6817662d"",
""LastModified"": ""2022-04-09T06:40:40+00:00"",
""IsActive"": true,
""Devices"": [{
""Id"": ""d58f034b"",
""IsActive"": true,
""SerialNumber"": ""754""
},
{
""Id"": ""005056963bac"",
""IsActive"": true,
""SerialNumber"": ""707""
}
]
}]
}
";
Rootobject? rootobject =
JsonSerializer.Deserialize(jsonString);
foreach (var datum in rootobject.data)
{
if (datum.Devices != null) {
Console.WriteLine("It at least one device present under Devices node");
}
foreach (var device in datum.Devices)
{
Console.WriteLine($"Id:{device.Id}");
}
}
}
}
}
Output:
If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.