Jil
Jil copied to clipboard
Better control over deserialization
Recently a lot of the JSON I need to parse looks like this:
{"prop1":"value1","prop2":"843.12","stats":[["123.45","0.01"],["567.89","599.0"],["111.11","0.07"]]}
But I need to deserialize it into classes like these:
public class A
{
[JilDirective(Name = "prop1")]
public string Prop1
{ get; set; }
[JilDirective(Ignore = true)]
public decimal Prop2
{ get; set; }
[JilDirective(Ignore = true)]
public List<B> Stats
{ get; set; }
}
internal class JilA : A
{
[JilDirective(Name = "prop2")]
public string JilProp2
{
get => throw new NotImplementedException();
set => this.Prop2 = decimal.Parse(value);
}
[JilDirective(Name = "stats")]
public List<List<string>> JilStats
{
get => throw new NotImplementedException();
set
{
var result = new List<B>(value.Count);
for (int i = 0; i < value.Count; i++)
{
var value1 = decimal.Parse(value[i][0]);
var value2 = decimal.Parse(value[i][1]);
result.Add(new B { Value1 = value1, Value2 = value2 });
}
this.Stats = result;
}
}
}
public class B
{
public decimal Value1
{ get; set; }
public decimal Value2
{ get; set; }
}
Notice I have to write a special deserialization class JilA
and deserialize a lot of the data myself. I do not see a way how to convert the above JSON into the data structure I need in more "native Jil" way. Is there?
Other solution I tried is also writing a special TextReader, which wraps the real JSON TextReader and basically waits until it sees "stats":[
in the Read()
procedure, and it hallucinates/rewrites a bunch of data to basically seamlessly rewrite the above JSON into:
{"prop1":"value1","prop2":843.12,"stats":[{"Value1": 123.45,"Value2":0.01},{"Value1":567.89,"Value2":599.0},{"Value1":111.11,"Value2":0.07}]}
But it is very error prone and all I do is just looking for the right bytes in the data rather than parsing the JSON in a safe manner.
Anyway, these sort of problems with having to write my own deserialization class JilA
are fairly common, because most of the financial API I have been working with return the stats data in a condensed nested array format rather than writing the data in array of objects.
So, I envision the following enhancement:
public class A
{
[JilDirective(Name = "prop1")]
public string Prop1
{ get; set; }
[JilDirective(Name = "prop2", UnderlyingType = JilUnderlyingTypes.String)]
public decimal Prop2
{ get; set; }
[JilDirective(Name = "stats")]
public List<B> Stats
{ get; set; }
}
[JilDirective(UnderlyingType = JilUnderlyingTypes.Array)]
public class B
{
[JilDirective(ArrayOffset = 0, UnderlyingType = JilUnderlyingTypes.String)]
public decimal Value1
{ get; set; }
[JilDirective(ArrayOffset = 1, , UnderlyingType = JilUnderlyingTypes.String)]
public decimal Value2
{ get; set; }
}
Where I can specify the UnderlyingType
, to instruct Jil that the decimals are wrapped in quotes. I can also change an object B
to be stored as array rather than object, and then use ArrayOffset
to specify property positions within that array.
I guess I could use dynamic deserialization to solve these problems, but probably with a major performance cost?