I want to deserialize the following JSON into my C# Tree object. The tree structure cannot be edited.
JSON:
{
"Root": {
"Type": 0,
"children": [
{
"Type": 1,
"Name": " SERVICES",
"children": [
{
"Type": 2,
"Name": " SERVICES",
"Code": "S01",
"children": [],
"leaves": [
{
"Type": 6,
"Code": "H-L-CWP-50",
"Uom": "SQM",
"Measurements": "SQM",
"BaseRate": "€20"
},
{
"Type": 6,
"Code": "HMS-REM-001-03",
"Uom": "SQ.M",
"Measurements": "SQ.M",
"BaseRate": "€6.38"
}
]
}
]
}
]
}
}
C# Tree:
public class Tree
{
public Root Root { get; set; }
public Tree()
{}
}
public class Root : Node
{
public override NodeType Type => NodeType.Root;
}
public class Group : Node
{
public override NodeType Type => NodeType.Group;
}
public class Category : Node
{
public override NodeType Type => NodeType.Category;
}
public class Type : Node
{
public override NodeType Type => NodeType.Type;
}
public class SubType : Node
{
public override NodeType Type => NodeType.SubType;
}
public class SubSubType : Node
{
public override NodeType Type => NodeType.SubsubType;
}
}
public abstract class Node
{
public int? ID { get; set; }
public int? FK { get; set; }
public string Name { get; set; }
public string Code { get; set; }
public List<Node> children { get; set; }
public List<Item> leaves { get; set; }
}
public class Item
{
public string Code { get; set; }
public string Desc { get; set; }
public string Uom { get; set; }
public float? Measurements { get; set; }
public int? FK { get; set; }
}
and the Tree is designed in a fashion where a Node can have a list of other Nodes as well as a list of Items; children and leaves respectively in JSON.
With the custom converter I built, I can deserialize the Nodes whenever no leaves exist, but populated leaves makes the JSON unrecognizable and an exception is thrown.
public class NodeConverter : JsonCreationConverter<Node> //notice the Node type here where in fact its a mixture of Nodes and Items.
{
protected override Node Create(Type objectType, JObject jObject)
{
switch ((Node.NodeType)jObject["Type"].Value<int>())
{
case Node.NodeType.Root:
return new Root();
case Node.NodeType.Group:
return new Group();
case Node.NodeType.Category:
return new Category();
case Node.NodeType.Type:
return new Type();
case Node.NodeType.SubType:
return new SubType();
case Node.NodeType.SubsubType:
return new SubSubType();
case Node.NodeType.Item: //I tried this but of course it won't work.
return new Item();
}
return null;
}
}
Any solutions/examples are highly appreciated!!!
Thanks guys.
For those encountering the same issues, I have solved my problem through a combination of different answers out there.
Classes Item and Node have been attributed with the JSON custom converter:
[JsonConverter(typeof(JSONTreeConverter))]
public abstract class Node
[JsonConverter(typeof(JSONTreeConverter))]
public class Item
this enables each class to use the custom converter before initializing.
Then the custom converter returns an object which is cast through reflection to the proper Node or Item type.
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
object targetObj = null;
JObject jo = JObject.Load(reader);
try
{
targetObj = Activator.CreateInstance(objectType); //instantiating concrete and known types
}
catch (Exception exc)
{
switch ((Node.NodeType)jo["Type"].Value<int>())
{
case Node.NodeType.Root:
targetObj = new Root();
break;
case Node.NodeType.Group:
targetObj = new Group();
break;
case Node.NodeType.Category:
targetObj = new ValescoCategory();
break;
case Node.NodeType.Type:
targetObj = new Type();
break;
case Node.NodeType.SubType:
targetObj = new SubType();
break;
case Node.NodeType.SubsubType:
targetObj = new SubSubType();
break;
case Node.NodeType.Item:
targetObj = new Item(); //now this is possible ;)
break;
}
}
foreach (PropertyInfo prop in objectType.GetProperties().Where(p => p.CanRead && p.CanWrite))
{
JsonPropertyAttribute att = prop.GetCustomAttributes(true)
.OfType<JsonPropertyAttribute>()
.FirstOrDefault();
string jsonPath = (att != null ? att.PropertyName : prop.Name);
JToken token = jo.SelectToken(jsonPath);
if (token != null && token.Type != JTokenType.Null)
{
object value = token.ToObject(prop.PropertyType, serializer);
prop.SetValue(targetObj, value, null);
}
}
return targetObj;
}
Deserializing as such: JsonConvert.DeserializeObject<Tree>(tree);
That's it! The other overridden function of JSON all return false with Write being not implemented.
Hope this helps someone else because it has taken me 3 days to get to.
Related
Usually, for derived types deserialization, you have to define a custom converter. I mean when there is a base class - Base and others derived from the Base. For that case you have to define a custom convevrter and use some data (maybe an enum) from each derived class to know to which type to convert the data. The problem is when this convertor is called for reference values, for which representation looks like {"$ref":"1"} and the convertor can't obtain any info from this.
Any ideas how to handle this?
Here is the source for better understanding:
public enum ElementType
{
Invalid = 0,
FirstElement,
SecondElement
}
public class SubElement
{
[JsonConstructor]
private SubElement() { }
public SubElement(string name, Element parent)
{
if (string.IsNullOrEmpty(name))
{
throw new ArgumentException("message", nameof(name));
}
Name = name;
Parent = parent ?? throw new ArgumentNullException(nameof(parent));
}
[JsonProperty]
public string Name { get; private set; }
[JsonProperty]
public Element Parent { get; private set; }
}
[JsonObject(IsReference = true)]
[JsonConverter(typeof(BaseConverter))]
public abstract class Element
{
[JsonConstructor]
protected Element() { }
public Element(string name, IList<SubElement> subelements)
{
Name = name;
Subelements = subelements;
}
[JsonProperty]
public string Name { get; private set; }
[JsonProperty]
public IList<SubElement> Subelements { get; private set; }
public abstract ElementType Type { get; }
}
public class FirstElement : Element
{
[JsonConstructor]
private FirstElement() { }
public FirstElement(string name, IList<SubElement> subelements) : base(name, subelements) { }
public override ElementType Type => ElementType.FirstElement;
}
public class BaseConverter : CustomCreationConverter<Element>
{
private ElementType elementType;
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var obj = JObject.ReadFrom(reader);
elementType = obj["Type"].ToObject<ElementType>();
return base.ReadJson(obj.CreateReader(), objectType, existingValue, serializer);
}
public override Element Create(Type objectType)
{
switch (elementType)
{
case ElementType.FirstElement:
return Activator.CreateInstance(typeof(FirstElement), true) as Element;
default:
throw new NotImplementedException();
}
}
}
class Program
{
static void Main(string[] args)
{
Element firstElement = new FirstElement("FirstElement", new List<SubElement>());
firstElement.Subelements.Add(new SubElement("Subelement1", firstElement));
firstElement.Subelements.Add(new SubElement("Subelement2", firstElement));
string serialized = JsonConvert.SerializeObject(firstElement);
Console.WriteLine(serialized);
Element deserialized = JsonConvert.DeserializeObject<Element>(serialized);
}
}
Serialization output:
{
"$id": "1",
"Type": 1,
"Name": "FirstElement",
"Subelements": [
{
"Name": "Subelement1",
"Parent": {
"$ref": "1"
}
},
{
"Name": "Subelement2",
"Parent": {
"$ref": "1"
}
}
]
}
If someone facing same scenario, I found a workaround by adding a dictionary in BaseConverter class, which maps the elements by their $id when they are created in Create method and, when the current object is an $ref, ReadJson method will return the corresponding mapped element.
This question already has answers here:
How to handle both a single item and an array for the same property using JSON.net
(9 answers)
Closed 3 years ago.
I am trying to process an object that can be either an array of object or just the object. Using the code below only works when the naics is an object and not an array. What am I doing wrong?
Here is the shortest example I can come up with:
[{
"section": "52.219-1.b",
"naics": [{
"naicsName": "Engineering Services",
"isPrimary": true,
"ExcpCounter": 1,
"isSmallBusiness": "Y",
"naicsCode": 541330
},
{
"naicsName": "Military and Aerospace Equipment and Military Weapons",
"isPrimary": true,
"ExcpCounter": 2,
"isSmallBusiness": "Y",
"naicsCode": 541330
}
]
},
{
"section": "52.219-1.b",
"naics": {
"naicsName": "Janitorial Services",
"isPrimary": true,
"isSmallBusiness": "Y",
"naicsCode": 561720
}
}
]
I will only have one of the types but I forced two in an array to force it into Quick Type.
My classes are:
[JsonProperty("naics", NullValueHandling = NullValueHandling.Ignore)]
public AnswerNaics Naics { get; set; }
public partial struct AnswerNaics
{
public AnswerNaic Naic;
public AnswerNaic[] NaicArray;
public static implicit operator AnswerNaics(AnswerNaic Naic) => new AnswerNaics { Naic = Naic };
public static implicit operator AnswerNaics(AnswerNaic[] NaicArray) => new AnswerNaics { NaicArray = NaicArray };
}
public partial class AnswerNaic
{
[JsonProperty("naicsName")]
public string NaicsName { get; set; }
[JsonProperty("hasSizeChanged")]
public string HasSizeChanged { get; set; }
[JsonProperty("isPrimary")]
public bool IsPrimary { get; set; }
[JsonProperty("ExcpCounter", NullValueHandling = NullValueHandling.Ignore)]
public long? ExcpCounter { get; set; }
[JsonProperty("isSmallBusiness")]
public string IsSmallBusiness { get; set; }
[JsonProperty("naicsCode")]
public string NaicsCode { get; set; }
}
internal class NaicsConverter : JsonConverter
{
public override bool CanConvert(Type t) => t == typeof(AnswerNaics) || t == typeof(AnswerNaics?);
public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer)
{
switch (reader.TokenType)
{
case JsonToken.StartObject:
var objectValue = serializer.Deserialize<AnswerNaic>(reader);
return new AnswerNaics { Naic = objectValue };
case JsonToken.StartArray:
var arrayValue = serializer.Deserialize<AnswerNaic[]>(reader);
return new AnswerNaics { NaicArray = arrayValue };
}
throw new Exception("Cannot unmarshal type AnswerNaics");
}
public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer)
{
var value = (AnswerNaics)untypedValue;
if (value.NaicArray != null)
{
serializer.Serialize(writer, value.NaicArray);
return;
}
if (value.Naic != null)
{
serializer.Serialize(writer, value.Naic);
return;
}
throw new Exception("Cannot marshal type Naics");
}
public static readonly NaicsConverter Singleton = new NaicsConverter();
}
I have more object or array nodes, but I am just trying to figure out one to be able to apply to all of them.
Since you cannot change the incoming JSON, you're going to need a custom converter instead. Something like this for example:
public class NaicsConverter : JsonConverter
{
public override bool CanConvert(Type t) => t == typeof(Naics);
public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer)
{
var naics = new Naics();
switch (reader.TokenType)
{
case JsonToken.StartObject:
// We know this is an object, so serialise a single Naics
naics.Add(serializer.Deserialize<Naic>(reader));
break;
case JsonToken.StartArray:
// We know this is an object, so serialise multiple Naics
foreach(var naic in serializer.Deserialize<List<Naic>>(reader))
{
naics.Add(naic);
}
break;
}
return naics;
}
public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
And the supporting classes:
public class Root
{
public string Section { get; set; }
[JsonConverter(typeof(NaicsConverter))]
public Naics Naics { get; set; }
}
// This isn't ideal, but it's quick and dirty and should get you started
public class Naics : List<Naic>
{
}
public class Naic
{
public string NaicsName { get; set; }
public bool IsPrimary { get; set; }
public string IsSmallBusiness { get; set; }
public long NaicsCode { get; set; }
}
And finally, to deserialise:
var settings = new JsonSerializerSettings {Converters = {new NaicsConverter()}};
var root = JsonConvert.DeserializeObject<Root[]>(Json, settings);
Now your object will get serialised into the list, but as a single item.
You can solve this using a dynamic field in your class.
Consider this JSON:
[
{
"field1": "val1",
"nested": [
{
"nestedField": "val2"
},
{
"nestedField": "val3"
}
]
},
{
"field1": "val4",
"nested":
{
"nestedField": "val5"
}
}
]
nested field is first an array with 2 objects and in the second appearance a single object. (similar to the JSON you posted)
So the class representation would look like:
public class RootObject
{
public string field1 { get; set; }
public dynamic nested { get; set; }
public List<NestedObject> NestedObjects
{
get
{
if(nested is JArray)
{
return JsonConvert.DeserializeObject<List<NestedObject>>(nested.ToString());
}
var obj = JsonConvert.DeserializeObject<NestedObject>(nested.ToString());
return new List<NestedObject> { obj };
}
}
}
public class NestedObject
{
public string nestedField { get; set; }
}
The Deserialization code is trivial using Newtonsoft JSON:
var objectList = JsonConvert.DeserializeObject<List<RootObject>>("some_json");
foreach(var v in objectList)
{
foreach(var n in v.NestedObjects)
{
Console.WriteLine(n.nestedField);
}
}
The only change is an implementation of NestedObjects ready only property. It check if the dynamic object is JArray or object. In any case, it returns a List of nested objects.
Lets say I have the below json.
{
"allitemscount":2,
"allitems":[
{"itemid":"1","itemname":"one"},
{"itemid":"2","itemname":"two"}],
"customitems":[
{"itemid":"3","itemname":"three"},
{"itemid":"4","itemname":"four"}]
}
and when deserializing this json, it should go to the below C# model.
public class response
{
public int allitemscount;
public List<item> items;
}
public class item
{
public string itemid;
public string itemname;
}
Question:
How to switch between allitems and customitems based on a condition? For eg., if useAllitems is true, allitems from the json to be filled in items and if useCustomItems is true, customitems to be filled in items property. Please help on how to do this.
Using JsonProperty on public List<item> items is allowing to switch between either allitems, but is there a way to deserialize based on the above mentioned condition.
I made it with writing our own ItemConverter which inherited from JsonConverter,
Sample model json that I use in my trying:
{
"allitemscount": 2,
"UseCustomItems": true,
"allitems": [
{
"itemid": "1",
"itemname": "one"
},
{
"itemid": "2",
"itemname": "two"
}
],
"customitems": [
{
"itemid": "3",
"itemname": "three"
},
{
"itemid": "4",
"itemname": "four"
}
]
}
Console application's main method:
static void Main(string[] args)
{
using (StreamReader r = new StreamReader(#"\model.json")) // json path
{
string json = r.ReadToEnd();
var deserializedJson = JsonConvert.DeserializeObject<Result>(json, new ItemConverter());
}
}
Models:
public class Result // main object
{
[JsonProperty("allitemscount")]
public long Allitemscount { get; set; }
public bool UseCustomItems { get; set; }
}
public class ResultA : Result // CustomItems Model
{
[JsonProperty("customitems")]
private List<Item> Items { get; set; }
}
public class ResultB : Result // AllItems Model
{
[JsonProperty("allitems")]
private List<Item> Items { get; set; }
}
public class Item
{
[JsonProperty("itemid")]
public string Itemid { get; set; }
[JsonProperty("itemname")]
public string Itemname { get; set; }
}
And the ItemConverter that we used while deserializing to object:
internal class ItemConverter : JsonConverter
{
private Type currentType;
public override bool CanConvert(Type objectType)
{
return typeof(Item).IsAssignableFrom(objectType) || objectType == typeof(Result);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject item = JObject.Load(reader);
if (item["UseCustomItems"] != null)
{
// save the type for later.
switch (item["UseCustomItems"].Value<bool>())
{
case true:
currentType = typeof(ResultA);
return item.ToObject<ResultA>(); // return result as customitems result
case false:
currentType = typeof(ResultB);
return item.ToObject<ResultB>(); // return result as allitems result
}
return item.ToObject<Result>();
}
// use the last type you read to serialise.
return item.ToObject(currentType);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
The result should be like bellowing image
I hope this solution help to you
You can deserialize above json by changing your response class as follows,
public class response{
public int allitemscount;
public List<item> allitems;
public List<item> customitems;
}
then use the following code,
var jsonData = "{\"allitemscount\":2, \"allitems\":[{\"itemid\":\"1\",\"itemname\":\"one\"}, {\"itemid\":\"2\",\"itemname\":\"two\"}],\"customitems\":[{\"itemid\":\"3\",\"itemname\":\"three\"},{\"itemid\":\"4\",\"itemname\":\"four\"}]}";
var data = JsonConvert.DeserializeObject<response>(jsonData);
foreach(var str in data.allitems) {
Console.WriteLine(str.itemid +'-'+str.itemname);
}
foreach(var str in data.customitems) {
Console.WriteLine(str.itemid +'-'+str.itemname);
}
Im having problem with deserializing json file into my class.
Json file looks like this:
{
"DataFile": {
"header":{
"version": "123",
"date": "01.01.01",
},
"customer": {
"fID": "12-35-58",
"nameCust": "CompanyName",
"adressCust":{
"zip": "0000",
"city": "Foovile",
"streetNr": "1",
"post": "FoovilePost",
"street": "DunnoStr",
},
},
"content": [
{
"invoice":{
"DFID":"538",
},
"invoice":{
"DFID":"500",
},
"invoice":{
"DFID":"550",
},
"receipt":{
"DFID":"758",
},
"receipt":{
"DFID":"75",
},
}
],
}
}
Everything before content array deserializes fine,so to keep things clear I'll skip parts of my class. Relevant bit looks like this:
class DFFile
{
public DF Df { get; set; }
}
class DF
{
public Header header { get; set; }
public Customer customer { get; set; }
public List<DFContent> content { get; set; }
}
class DFContent
{
public Invoice invoice { get; set; }
public Receipt receipt { get; set; }
}
class Invoice
{
public int DFID { get; set; }
}
class Receipt
{
public int DFID { get; set; }
}
And i deserialize into DFFile instance like this:
DFFile sample = JsonConvert.DeserializeObject<DFFile>(json);
My problem is that it deserializes without errors but sample.DF.content have only one element that have invoice and receipt with last id of each type. And result I'm looking for is list where there is new element for each item of json content array.
I can change my class but way this json is build is set in stone, can't do anything about it and have to deal with it.
Is there any way to stop it changing last element of content and add new one instead?
Your content is set up to hold an array but you only have one item in it which has three invoice and two receipt values. Assuming you want your DFContent to hold either a receipt or invoice, change it to look like this:
"content": [
{"invoice":{
"DFID":"538",
}},
{"invoice":{
"DFID":"500",
}},
{"invoice":{
"DFID":"550",
}},
{"receipt":{
"DFID":"758",
}},
{"receipt":{
"DFID":"75",
}}
],
Since you cannot change the JSON I assumed that you can change your class structure.
Please consider this classes:
class DF
{
// Other properties...
[JsonConverter(typeof(FunnyListConverter))]
public List<Content> content { get; set; }
}
class Content
{
public int DFID { get; set; }
}
class Invoice : Content
{
}
class Receipt : Content
{
}
And here is the FunnyListConverter:
public class FunnyListConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var content = new List<Content>();
var currentType = "";
Invoice currentInvoice = null;
Receipt currentReceipt = null;
while (reader.Read())
{
if (reader.TokenType == JsonToken.EndArray)
{
break;
}
if (reader.Value?.ToString() == "invoice")
{
currentInvoice = new Invoice();
currentType = "invoice";
}
if (reader.Value?.ToString() == "receipt")
{
currentReceipt = new Receipt();
currentType = "receipt";
}
if (reader.Path.Contains("DFID") && reader.Value?.ToString() != "DFID")
{
switch (currentType)
{
case "invoice":
currentInvoice.DFID = int.Parse(reader.Value.ToString());
content.Add(currentInvoice);
currentInvoice = null;
break;
case "receipt":
currentReceipt.DFID = int.Parse(reader.Value.ToString());
content.Add(currentReceipt);
currentReceipt = null;
break;
}
}
}
return content;
}
public override bool CanConvert(Type objectType)
{
return true;
}
if (reader.Value?.ToString() == "receipt")
{
currentReceipt = new Receipt();
currentType = "receipt";
}
if (reader.Path.Contains("DFID") && reader.Value?.ToString() != "DFID")
{
switch (currentType)
{
case "invoice":
currentInvoice.DFID = int.Parse(reader.Value.ToString());
content.Add(currentInvoice);
currentInvoice = null;
break;
case "receipt":
currentReceipt.DFID = int.Parse(reader.Value.ToString());
content.Add(currentReceipt);
currentReceipt = null;
break;
}
}
}
return content;
}
public override bool CanConvert(Type objectType)
{
return true;
}
}
I stumbled upon a service that outputs JSON in the following format:
{
"Author": "me",
"Version": "1.0.0",
"data.Type1": {
"Children": [
{
"data.Type1": {
"Children": [
{
"data.Type2": {
"name": "John",
"surname": "Doe"
}
}
]
}
},
{
"data.Type3": {
"dob": "1990-01-01"
}
}
]
}
}
Data type names are preserved as property names and their values are the actual objects. They all start with a data. prefix.
What I'd like to get afterwards is something like this:
{ // Root
"Author": "me",
"Version": "1.0.0",
"Children": [ // Type1
{
"Children": [ // Type1
{ // Type2
"Name": "John",
"Surname": "Doe"
}
]
},
{ // Type3
"DoB": "1990-01-01"
}
]
}
with the following classes:
class Type1 {
ICollection<object> Children { get; set; }
}
class Type2 {
public string Name { get; set; }
public string Surname { get; set; }
}
class Type3 {
public DateTime DoB { get; set; }
}
class Root
{
public string Author { get; set; }
public string Version { get; set; }
public Type1 Children { get; set; }
}
Question
How can I deserialize this into added C# classes, taking into account the data types and removing them from the tree?
I've tried with a custom JsonConverter, but am struggling with how to dynamically choose the converter, since the easiest way would be to put an attribute on the property, but it is not supported.
A small example would be great.
Although this JSON format is somewhat unusual and resists the use of attributes due to the dynamic property names, it is still possible to make a JsonConverter to deserialize it into your preferred class structure with one small change: I would recommend you change the Children property in the Root class to be an ICollection<object> to mirror the Children property in the Type1 class. As it is now, it does not match the structure of your desired output (where Children is shown as an array, not an object) and would otherwise require additional code in the converter to handle properly.
class Root
{
public string Author { get; set; }
public string Version { get; set; }
public ICollection<object> Children { get; set; }
}
Here is what I came up with for the converter (assuming the above change is made):
class CustomConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(Root));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject obj = JObject.Load(reader);
Root root = new Root();
root.Author = (string)obj["Author"];
root.Version = (string)obj["Version"];
root.Children = ((Type1)DeserializeTypeX(obj, serializer)).Children;
return root;
}
private object DeserializeTypeX(JObject obj, JsonSerializer serializer)
{
JProperty prop = obj.Properties().Where(p => p.Name.StartsWith("data.")).First();
JObject child = (JObject)prop.Value;
if (prop.Name == "data.Type1")
{
List<object> children = new List<object>();
foreach (JObject jo in child["Children"].Children<JObject>())
{
children.Add(DeserializeTypeX(jo, serializer));
}
return new Type1 { Children = children };
}
else if (prop.Name == "data.Type2")
{
return child.ToObject<Type2>(serializer);
}
else if (prop.Name == "data.Type3")
{
return child.ToObject<Type3>(serializer);
}
throw new JsonSerializationException("Unrecognized type: " + prop.Name);
}
public override bool CanWrite
{
get { return false; }
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
Armed with this converter you can deserialize to your classes like this:
Root root = JsonConvert.DeserializeObject<Root>(json, new CustomConverter());
You can then serialize to the new format like this:
JsonSerializerSettings settings = new JsonSerializerSettings
{
DateFormatString = "yyyy-MM-dd",
Formatting = Formatting.Indented
};
Console.WriteLine(JsonConvert.SerializeObject(root, settings));
Fiddle: https://dotnetfiddle.net/ESNMLE
Not sure if this will work but have you tried using Newtonsoft.Json to serialize the object and include JsonProperty tags on the class properties? I know this will work when deserializing Json into a class.
<JsonProperty("user_id")>
Public Property UserID As String
//Converts Json {user_id: 123} to class.UserID = 123
To Serialize with Newtonsoft, first include Newtonsoft into the project then
Dim stringJson As String = Newtonsoft.Json.JsonConvert.SerializeObject(root)