Validate object using json schema in C# - c#

I'm trying to use a json shema to validate an incoming objet parameter in a C# api.
Here is my api proto :
void BuildSqlQueryFromSegment(JoinDefinition jsonDef);
JsonDefinition is a complex objects, with lots of properties. Properties values are depending each other, this is why simple validateur attribute like Required, Min, Max can't be used here.
One solution would be to pass a string instead of the type object :
void BuildSqlQueryFromSegment(string jsonDef) {
// Check shema here, using Json.NET Schema
// if ok, deserialize and get the JsonDefition object instance
}
I'm able to implment this quite easily, but i find this solution not smart.
What i'm looking for is something like this :
void BuildSqlQueryFromSegment([SchemaValidation('MySchemaResourceHere')] JoinDefinition jsonDef);
Does this kind of attribute exist ? If not, how can i implement it ? How can i act on incoming response json string to check the schema ?
Thanks for your help.

First you need to create JsonSchema from JoinDefinition class
JsonSchemaGenerator schemaGenerator = new JsonSchemaGenerator{ };
var o = new JoinDefinition ();
JsonSchema Objschema = schemaGenerator.Generate(o.GetType());
than get Jsonschema from string
JObject jObject= JObject.Parse(JsonString);
bool valid = jObject.IsValid(Objschema);
If JsonString schema match from class json schema it would return true else false
You will have to use below namespace
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Schema;

Related

Using System.Text.Json, how do I get a "object" out of a extension data object?

I have a class written for ProblemDetails. I switched from NewtonSoft to System.Text.Json. I am trying to get the list of "errors", which is a deserialized into the Extensions property, which is decorated with [JsonExtensionData].
I cannot figure out how to enumerate and read the "errors", which inevitable is a dictionary.
I get to the point where I can get the "errors" back a JsonElement, but from JsonElement there is not "j.GetJsonElement", just j.GetString(), j.GetInt(), etc.
How do I get the elements below "errors"?
[Fact]
public void DeserializeTest()
{
var json = "{\"type\":\"https://tools.ietf.org/html/rfc7231#section-6.5.1\",\"title\":\"One or more validation errors occurred.\",\"status\":400,\"traceId\":\"00-ccf1398eea1494aef2e3fa0f07a34899-09a93c2176a88981-00\",\"errors\":{\"BottomRightX\":[\"Bottom Right X must be greater than Top Left X.\"],\"BottomRightY\":[\"Bottom Right Y must be greater than Top Left Y.\"]}}";
var problemDetails = JsonSerializer.Deserialize<ProblemDetails>(json);
problemDetails.Should().NotBeNull();
problemDetails.Title.Should().NotBeNullOrEmpty();
problemDetails.Status.Should().Be(400);
problemDetails.Extensions.Should().NotBeNullOrEmpty();
var j = problemDetails.Extensions.Should().ContainKey("errors").WhoseValue;
j.ValueKind.Should().Be(JsonValueKind.Object);
// all above pass
var x = j.GetJsonElement() ????;
}
My best guest is you can create a customer deserialization and in the errors value include a property type, to use it in as part as the custom serialization. But its not recommended. If U can never use object in Json Serialization, only Strong Type Objects to avoid this kind situation.
At this moment you should expect either some value or a property. To process properties - use GetProperty/TryGetProperty which has out parameter of JElement type:
j.TryGetProperty("BottomRightY", out JElement bottomRightY).Should().BeTrue();

NewtonSoft JsonConvert SerializeObject Dictionary of Object Escape Chars

I'm having some trouble using the JsonConvert.SerializeObject method concerning escape chars in WCF. My web method returns a Stream as follows:
return new MemoryStream(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(myObject)));
This works fine apart from one of the properties of myObject is a Dictionary of <string, object>. All of the simple types serialize correctly, however when I try and add my custom class as a value I get the type returned instead of the data. On realising this comes from the serialiser calling .ToString on my custom class I've tried overriding it with:
public override string ToString()
{
return JsonConvert.SerializeObject(this);
}
However the returned data now includes escape chars
{
"my_dictionary": {
"elem_1": "{\"Prop1\":null,\"Prop2\":3}",
"elem_2": "{\"Prop1\":null,\"Prop2\":3}",
"int_property" : 123
}
}
Any ideas on how I could avoid my custom class being escaped in this way and returned as an array?
Thanks in advance, Matt
I use JavaScriptSerializer (just replace "Object" with your custom class)
using System.Web.Script.Serialization;
List<Object> list = new List<Object>();
JavaScriptSerializer jss = new JavaScriptSerializer();
string res = jss.Serialize(list);
and get this format with "res" value:
[{"IdEmpresa":1,"Nombre":"Test","URL":"http:/localhost:8080/","Activo":true},IdEmpresa":2,"Nombre":"Test2,","URL":"http://localhost:8081/","Activo":true}]
I've realised there was a mistake in the code. The class that was being serialised actually returned a Dictionary the conversion of the object to a string was causing the behaviour I'd observed and in reality the serializer was perfectly able to serialise the objects correctly.

How to receive JSON data into Web API ApiController method?

I'm writing a Web API ApiController with several PUT methods that receive JSON data. The JSON is not deterministic and hence cannot be hard-mapped to a custom C# object, but needs to be received as Dictionaries/Sequences (Maps/Lists).
I have tried using an IDictionary for the data parm of the PUT method in the controller, and this sort of works -- the data appears to be mapped from JSON to the dictionary. However, it's necessary to declare the dictionary as <String,Object>, and there's no clear way to then retrieve the Object values as their appropriate types. (I've found a few suggested kluges in my searching, but they are just that.)
There is also a System.Json.JsonObject type which I finally managed to get loaded via NuGet, but when I use that the system does not appear to know how to map the data.
How is this typically done? How do you implement an ApiController method that receives generic JSON?
I can see three basic approaches:
Somehow make Dictionary/Sequence work with Object or some such.
Make something like System.Json.JsonObject work, perhaps by swizzling the routing info.
Receive the JSON as a byte array and then parse explicitly using one of the C# JSON toolkits available.
(As to how dynamic the data is, JSON objects may have missing entries or extraneous entries, and in some cases a particular entry may be represented as either a single JSON value or a JSON array of values. (Where "value" is JSON array, object, string, number, Boolean, or null.) In general, except for the array/not array ambiguity, the relation between keys and value types is known.)
(But I should note that this is a large project and I'll be receiving JSON strings from several other components by other authors. Being able to examine the received type and assert that it's as expected would be quite useful, and may even be necessary from a security standpoint.)
(I should add that I'm a relative novice with C# -- have only been working with it for about 6 months.)
You've got to know what kind of data you're expecting, but I have had success doing this in the past using dynamic typing.
Something like this:
[Test]
public void JsonTester()
{
string json = "{ 'fruit':'banana', 'color':'yellow' }";
dynamic data = JsonConvert.DeserializeObject(json);
string fruit = data["fruit"];
string color = data["color"];
Assert.That(fruit == "banana");
Assert.That(color == "yellow");
}
Edit:
You either need to know the type you want to deserialize to beforehand - in which case you can deserialize it to that type immediately.
Or you can deserialize it to a dynamic type, and then convert it to your static type once you know what you want to do with it.
using Newtonsoft.Json;
using NUnit.Framework;
public class DTO
{
public string Field1;
public int Field2;
}
public class JsonDeserializationTests
{
[Test]
public void JsonCanBeDeserializedToDTO()
{
string json = "{ 'Field1':'some text', 'Field2':45 }";
var data = JsonConvert.DeserializeObject<DTO>(json);
Assert.That(data.Field1 == "some text");
Assert.That(data.Field2 == 45);
}
[Test]
public void JsonCanBeDeserializedToDynamic_AndConvertedToDTO()
{
string json = "{ 'Field1':'some text', 'Field2':45 }";
var dynamicData = JsonConvert.DeserializeObject<dynamic>(json);
var data = new DTO { Field1 = dynamicData["Field1"], Field2 = dynamicData["Field2"] };
Assert.That(data.Field1 == "some text");
Assert.That(data.Field2 == 45);
}
}

How to create a json string where a property contains a dot (period)?

I'm trying to send an HttpRequest that takes a JSON object like this:
{
"some.setting.withperiods":"myvalue"
}
I've been creating anonymous objects for my other requests, but I can't do that with this one since the name contains a dot.
I know I can create a class and specify the [DataMember(Name="some.setting.withperiods")] attribute, but there must be a more lightweight solution.
There is no "easy" way to achieve this because the . in C# is reserved.
However, you could achieve something pretty close by using a dictionary and collection initializer. It's still somewhat isolated, and doesn't require you to create a custom class.
var obj = new Dictionary<string, object>
{
{ "some.setting.withperiods", "myvalue" }
};
var json = JsonConvert.SerializeObject(obj);
//{"some.setting.withperiods":"myvalue"}
You can use "JsonProperty" attribute for the same For example
[JsonProperty(".Name")]
public string Name { get; set; }
On top of this I want to add how to retrieve the data from the json where it has name property starting with special character as in Web API 2.0 token has ".issued".
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
var jsonRespons="json response from the web api";
var issue= JObject.Parse(jsonResponse).GetValue(".issued");
if you do it from in javascript, you can easily go back and forth, as shown with:
var obj = {
"some.setting.withdots":"myvalue"
};
var json = JSON.stringify(obj);
console.log(json);
var str = JSON.parse(json);
console.log(str);
have you tried putting it into a serialized string and sending that, then deserializing on the client-side?
you could do something like
var myAnnon = new
{
WithPeriod = "value"
};
var j = JsonConvert.SerializeObject(myAnnon);
j = j.Replace("WithPeriod", "some.setting.withdots");
You can use a JObject (part of Json.Net's LINQ-to-JSON API) to create the JSON in question:
string json = new JObject(new JProperty("some.setting.withperiods", "myvalue")).ToString();
Fiddle: https://dotnetfiddle.net/bhgTta
You could try prefixing your member names with a # to allow use of literals, but the way to do it is using [DataMember] as you have already mentioned in your question.

Turn a JSON string into a dynamic object

I'm trying to create a dynamic object from a JSON string in C#. But i can't get it done.
Normally i would get a JSON string through a web service call but in this case I simply created a simple class which I turn into a JSON string. Then I try to turn it back into a dynamic object with the exact same structure as if it was an instance of the Entity class. But that's where I'm having trouble.
This is the class that i turn into a JSON string:
public class Entity
{
public String Name = "Wut";
public String[] Scores = {"aaa", "bbb", "ccc"};
}
Then in somewhere in my code i do this:
var ent = new Entity();
// The Serialize returns this:
// "{\"Name\":\"Wut\",\"Scores\":[\"aaa\",\"bbb\",\"ccc\"]}"
var json = new JavaScriptSerializer().Serialize(ent);
dynamic dynamicObject1 = new JavaScriptSerializer().DeserializeObject(json);
dynamic dynamicObject2 = Json.Decode(json);
When I debug this code then i see that the first dynamicObject1 returns a Dictionary. Not really what I'm after.
The second dynamicObject2 looks more like the Entity object. It has a property called Name with a value. It also has a dynamic array called Scores, but for some reason that list turns out to be empty...
Screenshot of empty Scores property in dynamic object:
So I'm not having any luck so far trying to cast a JSON string to a dynamic object. Anyone any idea how I could get this done?
Using Json.Net
dynamic dynamicObject1 = JsonConvert.DeserializeObject(json);
Console.WriteLine(dynamicObject1.Name);
Using Json.Net but deserializing into a ExpandableOBject, a type that is native to C#:
dynamic obj= JsonConvert.DeserializeObject<ExpandoObject>(yourjson);
If the target type is not specified then it will be convert to JObject type instead. Json object has json types attached to every node that can cause problems when converting the object into other dynamic type like mongo bson.

Categories