(JSON) parsing and helpful tips..

Who didn’t hear of JSON yet!! If not which world are you living in :P.
It stands for JavaScript Object Notation.
Fancy name right! but in simple words it is just a key with its matching value, which could be of any type and as much deep as we want.
Benefits, it is simple, easy and pretty size efficient when working with it in APIs, saving some data or many other use cases.
But sometimes it gets tricky when trying to parse the data into the needed types, as it may contain some additional characters or could be of a different format than the normal parser can use.
Newtonsoft is the nuget package that we are going to use to demonstrate working with raw JSON and how to do custom converter and more, Lets begin!
Reading simple JSON:
{
"key_str" :"value",
"key_int": 1,
"key_bool" : true
}
So we have our Josn, now I have created a new Asp.net Core (API) project just to keep things simple (using the default ValuesController).
Now that we are setup lets start by parsing and reading it in our controller.
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
[HttpPost]
public IActionResult Post(object data)
{
return Ok(data);
}
}
So pretty simple just our good old normal API endpoint.
in here it just returns what ever we send back, not much but a good starting point to make sure that we have our data.
Lets make it a bit more by creating a model and actually getting the parsed data not some plain object.
public class ValuesPostModel
{
[JsonProperty("key_str")]
public string KeyStr { get; set; }
[JsonProperty("key_int")]
public int KeyInt { get; set; }
[JsonProperty("key_bool")]
public bool KeyBool { get; set; }
}
[HttpPost]
public IActionResult Post(ValuesPostModel data)
{
return Ok(data);
}
We can get the data all in good shape and parsed due to the default JSON deserializer that is hooked up along the request pipeline to reach the controller.
Now that is all good but pretty simple and good.
Sometimes the user might forget to send some required values or we want to block some properties to be sent back or the formatting of the data is not as wanted and could break the parsing.
Here we are going to list some of the attributes that can help us.
Ignoring some properties…
Some of the data is not meant to be sent back to the users or we want to decrease the size of our response we can easily do that by JSONIgnoreAttribute.
[JsonIgnore]
public object Secret{ get; set; }
This will insure that our secret property never get sent back and just kept as is.
Requiring some properties…
A lot of cases we need some properties to be there so we can preform the needed action.
Adding some extra checks inside the controller is always a bit boring and just redundant code.
To fix that we can set the JSONRequired attribute on what properties we need which will cause to return ((400) bad request) when that part of data is not provider so it makes sure we got what we need.
[JsonRequired]
[JsonProperty("id")]
public int Id { get; set; }
And when not sending (Id) will result in a (400 Bad Request).

Converting complex objects…
Lets take an example and see where this issue could happen, take this:
{
"dateKey" :"20200801"
}
So here we are getting a date key in (YYYYMMDD) format that you want to put it in a DateTime object.
Following the first approach by adding a property and just mapping it, will result in validation issues as it is unable to parse the data.
A simple fix is to use JSONConverter, this will let us manipulate the data to our need.
public class DatetimeJsonConverter : JsonConverter<DateTime>
{
public string Format { get; set; }
public override DateTime ReadJson(JsonReader reader, Type objectType, DateTime existingValue, bool hasExistingValue, JsonSerializer serializer)
{
if (reader.Value != null && DateTime.TryParseExact(reader.Value.ToString(), Format, null, System.Globalization.DateTimeStyles.None, out DateTime date))
{
return date;
}
return default(DateTime);
}
public override void WriteJson(JsonWriter writer, DateTime value, JsonSerializer serializer)
{
writer.WriteRawValue(value.ToString(Format));
}
public DatetimeJsonConverter(string format)
{
Format = format;
}
}
Here we created our converter inheriting from JSONConverter while giving the type we want to convert to.
This will give us access to two overrides which we can manipulate the read and write of data as we like, which mean we can read it as dateKey and return it as what ever type or shape we want, in here I am just writing a raw value.
I also included a constructor that would take a the format of which we know the data is reaching in, which makes it pretty dynamic to use.
[JsonProperty("dateKey")]
[JsonConverter(typeof(DatetimeJsonConverter),"yyyyMMdd")]
public DateTime DateKey { get; set; }
So simple to consume by just providing its type and any parameters that we need to send for constructor (Can add as many as you need just make sure to have the corresponding constructor defined)
And Wooh! our data is parsed and we can use the converter in any other case with simple just changing the format parameter.
This can be applied to many other use cases if you find hard timing parsing it leave a comment and we can chat about achieving the wanted goal.
Conclusion :)..
In here we barely just scratched the surface on some of the most used Attributes when working with JSON data.
There are plenty more!! which are really so helpful in some seniors.
Combing those attributes together will open the true power of it so make sure to try them all!
No Comments