How To Serialize a class that derives from a Dictionary - c#

I am attempting to serialize/deserialize the following class to and from Json using Json.Net:
public class ChildDictionary:Dictionary<Employee, double>
{
public string Name { get; set; }
}
I have found the information here, here, and here that are related but none of them deal specifically with what the syntax should look like for this case where we derive from a Dictionary.
Employee successfully serializes with Json.Net on its own. It looks like this:
[JsonObject(MemberSerialization.OptIn)]
public class Employee
{
[JsonProperty]
public string Name { get; set; }
[JsonProperty]
public double Factor { get; set; }
[JsonProperty]
public List<ILoadBuilder> LoadBuilders = new List<ILoadBuilder>();
[JsonConstructor]
public LoadCause(string name, double factor, List<ILoadBuilder> loadBuilders)
{
this.Name = name;
this.DurationFactor = Factor;
this.LoadBuilders = loadBuilders;
}
}
I don't care what the Json looks like in the end as long as I can write and read it without losing data
Any suggestions of what the code to accomplish this should look like? Both a Custom JsonConverter or Attributes are fine solutions.

Because your dictionary has both a complex key and additional properties, you will need to use a custom JsonConverter to serialize and deserialize this class. Below is a converter that should do the job. It handles the serialization in two parts: first it uses reflection to deal with any read-write properties on the class, then it casts the object to a dictionary interface to handle the key-value pairs. The latter are written to the JSON as an array of objects with Key and Value properties so that the complex keys are managed without needing to jump through extra hoops.
public class ComplexDictionaryConverter<K,V> : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (objectType.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IDictionary<K,V>)));
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
JObject obj = new JObject();
foreach (PropertyInfo prop in GetReadWriteProperties(value.GetType()))
{
object val = prop.GetValue(value);
obj.Add(prop.Name, val != null ? JToken.FromObject(val, serializer) : new JValue(val));
}
JArray array = new JArray();
foreach (var kvp in (IDictionary<K, V>)value)
{
JObject item = new JObject();
item.Add("Key", JToken.FromObject(kvp.Key, serializer));
item.Add("Value", kvp.Value != null ? JToken.FromObject(kvp.Value, serializer) : new JValue(kvp.Value));
array.Add(item);
}
obj.Add("KVPs", array);
obj.WriteTo(writer);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject obj = JObject.Load(reader);
IDictionary<K, V> dict = (IDictionary<K, V>)Activator.CreateInstance(objectType);
foreach (PropertyInfo prop in GetReadWriteProperties(objectType))
{
JToken token = obj[prop.Name];
object val = token != null ? token.ToObject(prop.PropertyType, serializer) : null;
prop.SetValue(dict, val);
}
JArray array = (JArray)obj["KVPs"];
foreach (JObject kvp in array.Children<JObject>())
{
K key = kvp["Key"].ToObject<K>(serializer);
V val = kvp["Value"].ToObject<V>(serializer);
dict.Add(key, val);
}
return dict;
}
private IEnumerable<PropertyInfo> GetReadWriteProperties(Type type)
{
return type.GetProperties().Where(p => p.CanRead && p.CanWrite && !p.GetIndexParameters().Any());
}
}
To use the converter, you can mark your class with a [JsonConverter] attribute like this (be sure the generic parameters match those of the dictionary your class inherits from):
[JsonConverter(typeof(ComplexDictionaryConverter<Employee, double>))]
public class ChildDictionary : Dictionary<Employee, double>
{
...
}
Here is a demo showing a full round-trip:
class Program
{
static void Main(string[] args)
{
ChildDictionary dict = new ChildDictionary();
dict.Name = "Roster";
dict.Add(new Employee { Id = 22, Name = "Joe", HireDate = new DateTime(2012, 4, 17) }, 1923.07);
dict.Add(new Employee { Id = 45, Name = "Fred", HireDate = new DateTime(2010, 8, 22) }, 1415.25);
string json = JsonConvert.SerializeObject(dict, Formatting.Indented);
Console.WriteLine(json);
dict = JsonConvert.DeserializeObject<ChildDictionary>(json);
Console.WriteLine("Name: " + dict.Name);
foreach (var kvp in dict)
{
Console.WriteLine("Employee Id: " + kvp.Key.Id);
Console.WriteLine("Employee Name: " + kvp.Key.Name);
Console.WriteLine("Employee Hire Date: " + kvp.Key.HireDate);
Console.WriteLine("Amount: " + kvp.Value);
Console.WriteLine();
}
}
}
[JsonConverter(typeof(ComplexDictionaryConverter<Employee, double>))]
public class ChildDictionary : Dictionary<Employee, double>
{
public string Name { get; set; }
}
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime HireDate { get; set; }
}
Output:
{
"Name": "Roster",
"KVPs": [
{
"Key": {
"Id": 22,
"Name": "Joe",
"HireDate": "2012-04-17T00:00:00"
},
"Value": 1923.07
},
{
"Key": {
"Id": 45,
"Name": "Fred",
"HireDate": "2010-08-22T00:00:00"
},
"Value": 1415.25
}
]
}
Name: Roster
Employee Id: 22
Employee Name: Joe
Employee Hire Date: 4/17/2012 12:00:00 AM
Amount: 1923.07
Employee Id: 45
Employee Name: Fred
Employee Hire Date: 8/22/2010 12:00:00 AM
Amount: 1415.25
Fiddle: https://dotnetfiddle.net/fTfoIk

Related

How to create custom serializer for values in dictionary?

I have the following class:
public class Farm
{
public string County {get;set;}
public Dictionary<string, object> FarmItems {get;set;}
}
I need to implement a custom serializer/deserializer that, if it's a integer in the value, store it in the DB as a string and then deserialize it back to a integer
I've looked at the docs and they gave details on how to do it for single values but not for dictionaries https://mongodb.github.io/mongo-csharp-driver/2.12/reference/bson/serialization/
Also, the docs don't mention how to implement it, do I just add an attribute after creating my class like so:
[BsonSerializer(typeof(MyCustomSerializer))]
public Dictionary<string, object> FarmItems {get;set;}
here you go:
public class MyDictionarySerialzer : SerializerBase<Dictionary<string, object>>
{
public override void Serialize(BsonSerializationContext ctx, BsonSerializationArgs args, Dictionary<string, object> dictionary)
{
if (dictionary == null)
{
ctx.Writer.WriteStartArray();
ctx.Writer.WriteEndArray();
return;
}
ctx.Writer.WriteStartArray();
foreach (var kvPair in dictionary)
{
ctx.Writer.WriteStartDocument();
ctx.Writer.WriteName("k");
ctx.Writer.WriteString(kvPair.Key);
ctx.Writer.WriteName("v");
if (kvPair.Value is int)
ctx.Writer.WriteString(kvPair.Value.ToString());
else
BsonSerializer.Serialize(ctx.Writer, kvPair.Value);
ctx.Writer.WriteEndDocument();
}
ctx.Writer.WriteEndArray();
}
public override Dictionary<string, object> Deserialize(BsonDeserializationContext ctx, BsonDeserializationArgs args)
{
Dictionary<string, object> dict = new();
switch (ctx.Reader.CurrentBsonType)
{
case BsonType.Array:
foreach (var val in BsonSerializer.Deserialize<BsonArray>(ctx.Reader))
{
string key = val["k"].AsString;
object value = BsonSerializer.Deserialize<object>(val["v"].ToJson());
if (int.TryParse(value?.ToString(), out var parsedInt))
value = parsedInt;
dict.Add(key, value);
}
return dict;
default:
throw new BsonSerializationException("Unable to deserialize dictionary!");
}
}
}
if you are storing any complex entities in the dictionary values, you have to register (on app startup) that complex type with mongo driver like so (or deserialization will fail):
BsonClassMap.RegisterClassMap<ComplexItem>();
simply decorate the property like so:
public class Farm
{
[BsonSerializer(typeof(MyDictionarySerialzer))]
public Dictionary<string, object> FarmItems { get; set; }
}
example entity:
var example = new Farm
{
FarmItems = new Dictionary<string, object>()
{
{"empty",null },
{"string","test string" },
{"int",100 },
{"complex",new ComplexItem{ Age = 10, Name = "test" } }
}
};
it will be serialized to the db like so:
{
"FarmItems" : [
{
"k" : "empty",
"v" : null
},
{
"k" : "string",
"v" : "test string"
},
{
"k" : "int",
"v" : "100"
},
{
"k" : "complex",
"v" : {
"_t" : "ComplexItem",
"Name" : "test",
"Age" : 10
}
}
]
}

How to deserialize JSON with dynamic and static key names in C#

I have to deserialize a response from an api which has the following structure:
[
{
"starttime": "...",
"endtime": "....",
"var1": {},
"var2": {}
},
{
"starttime": "...",
"endtime": "....",
"var1": {},
"var3": {}
},
{
"starttime": "...",
"endtime": "....",
"var1": {}
}
]
Some insights:
The JSON is an array of objects
Every object inside the array will ALWAYS have the properties "starttime" and "endtime"
Objects "var1", "var2", "var3" will ALWAYS have the same properties inside them... but the problem is that the object keys (var1, var2 or var3) are dynamic. It can be any string, and also the amount of this kind of objects is dynamic (I could have 3, or zero "var" objects).
I was thinking something like this, to deserialize the JSON string into a List of objects with properties "starttime", "endtime" and a dictionary with all the "var" objects.
public class MyResponse
{
[JsonProperty(PropertyName = "starttime")]
public string StartTime { get; set; }
[JsonProperty(PropertyName = "endtime")]
public string EndTime { get; set; }
public Dictionary<string, VarObject> VarData { get; set; }
}
But the VarData property is always null.
Has anyone tried something like this?
You have two options, the first is to deserialise directly to a List<Dictionary<string, object>>, for example:
var responses = JsonConvert.DeserializeObject<List<Dictionary<string, object>>>(json);
Alternatively, if you are stuck on using your object, you will need to write a custom converter. For example, something like this:
public class MyResponseConverter : JsonConverter
{
public override bool CanConvert(Type type) => type == typeof(MyResponse);
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var responseObject = JObject.Load(reader);
MyResponse response = new MyResponse
{
StartTime = (string)responseObject["starttime"],
EndTime = (string)responseObject["endtime"],
};
var varData = new Dictionary<string, object>();
foreach (var property in responseObject.Properties())
{
if(property.Name == "starttime" || property.Name == "endtime")
{
continue;
}
varData.Add(property.Name, property.Value);
}
response.VarData = varData;
return response;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
// If you want to write to JSON, you will need to implement this method
throw new NotImplementedException();
}
}
And your class would change slightly to this:
[JsonConverter(typeof(MyResponseConverter))]
public class MyResponse
{
[JsonProperty(PropertyName = "starttime")]
public string StartTime { get; set; }
[JsonProperty(PropertyName = "endtime")]
public string EndTime { get; set; }
public Dictionary<string, object> VarData { get; set; }
}
Now you deserialise like this:
var responses = JsonConvert.DeserializeObject<List<MyResponse>>(json);
You can view example Here https://dotnetfiddle.net/QgXWQi.
But for more flexibility, this logic is better to implement in method that marked as [OnDeserialized]
Like here https://www.newtonsoft.com/json/help/html/SerializationAttributes.htm
The main idea is to parse it as JObject and then convert to Dictionary
var jObj = JObject.Parse(jsonText);
var varData = jObj
.Children<JProperty>()
.Where(p => p.Name != "starttime" && p.Name != "endtime")
.ToDictionary(x=> x.Name, x => ((JObject)x.Value).ToObject<VarObject>());

Print object with nested properties as string of comma separated key-value pairs

I have a Person class:
public class Person
{
public string Name { get; set; }
public string Surname { get; set; }
public Address Address { get; set; }
}
public class Address
{
public string Line1 { get; set; }
public string Line2 { get; set; }
}
As an end result, I would like to print out a Person instance as JSON, but I'd like it to be a huge string of key-value pairs, e.g.:
"Name:John,Surname:Doe,Line1:Infinite Loop,Line2:California"
Notice that in the example above, I got rid of the actual class names (i.e. it prints out Line1 instead of Address.Line1) - i only care about all the name/value pairs.
So the end result would be an array of Persons:
"persons":[
"Name:John,Surname:Doe,Line1:Infinite Loop 1,Line2:California",
"Name:Jane,Surname:Doe,Line1:Infinite Loop 2,Line2:California"
]
As a starting point, I tried using reflection:
void Main()
{
var persons = new List<Person>();
persons.Add(new Person
{
Name = "John",
Surname = "Doe",
Address = new Address
{
Line1 = "Infinite Loop",
Line2 = "California"
}
});
foreach(var person in persons)
{
var properties = new List<string>();
foreach(var property in person.GetType().GetProperties())
{
properties.Add($"{property.Name}:{property.GetValue(person, null)}");
}
Console.WriteLine(string.Join(",", properties));
}
}
But I get the following output in LINQPad:
Name:John,Surname:Doe,Address:UserQuery+Address
I assume Address is not properly iterated upon because it's a nested object within Person. Even so, this doesn't look like the most clean/efficient approach.
You could do this using a custom JsonConverter like so:
class PersonConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(Person);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var pairs = JObject.FromObject(value)
.Descendants()
.OfType<JProperty>()
.Where(p => p.Value is JValue)
.Select(p => p.Name + ":" + p.Value);
writer.WriteValue(string.Join(",", pairs));
}
public override bool CanRead
{
get { return false; }
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
Then use it by passing the converter to JsonConvert.SerializeObject like this:
string json = JsonConvert.SerializeObject(obj, Formatting.Indented, new PersonConverter());
Here is a working demo: https://dotnetfiddle.net/L4YDsm
Add a ToString override to your class and return a collection of strings as JSON.
public class Person
{
public string Name { get; set; }
public string Surname { get; set; }
public Address Address { get; set; }
public override string ToString()
{
return $"Name:{Name},Surname:{Surname},Line1:{Address?.Line1},Line2:{Address?.Line2}";
}
}
You must implement the reflection in a way that it could go deeper into the structure of your object in order to do what you want. Here's a simple recursive and generic adaptation to your provided code.
public static string GetRecursivePropertyValues(object obj)
{
var properties = new List<string>();
foreach (var property in obj.GetType().GetProperties())
{
object currentPropertyValue = property.GetValue(obj);
if (property.PropertyType.IsPrimitive || property.PropertyType == typeof(string))
properties.Add($"{property.Name}:{currentPropertyValue}");
else
{
var subProperties = GetRecursivePropertyValues(currentPropertyValue);
properties.Add(subProperties);
}
}
return string.Join(";", properties);
}
This implementation first verifies if each property is defined with a primitive type or string (which are not considered primitive types in C#) and prints them normally if that's the case. Else, if the type is complex (like if it is declared as an Address instance), it recursivelly retrieves the properties of the complex object, and adds them to the resulting string.
You can call it like:
string propertiesStr = GetRecursivePropertyValues(person);
Edit: code now only flattens the object as required by OP (previous code sample used some rustic JSON formatting).
Using Newtonsoft.json
https://www.newtonsoft.com/json/help/html/SerializingJSON.htm
Check the above link... It will tell you how to serialize an object to json, it's important to note, you will want to add all your items to a list, then serialize the list into json to get the desired effect
Product product = new Product();
product.Name = "Apple";
product.ExpiryDate = new DateTime(2008, 12, 28);
product.Price = 3.99M;
product.Sizes = new string[] { "Small", "Medium", "Large" };
There example:
string output = JsonConvert.SerializeObject(product);
//{
// "Name": "Apple",
// "ExpiryDate": "2008-12-28T00:00:00",
// "Price": 3.99,
// "Sizes": [
// "Small",
// "Medium",
// "Large"
// ]
//}

Newtonsoft Json Serializer/Deserializer - how to use generic objects instead of JObject?

I have JSON specified by a restful service I am consuming that looks like this as an example:
{
"id": "97",
"name": "Tom Production",
"description": null,
"parameters": [
{
"first_parameter_name": "First Parameter Value"
},
{
"second_parameter_name": "Second Parameter Value"
}
]
}
Note that the property names id, name, description, and parameters are all established as part of the specification. The collection of generic parameters, shown in my example as "first_parameter_name" and "second_parameter_name" are not specified.... could be anything and I want to map them to generically typed objects.
I have declared an object for this as:
[DataContract (Name = "MyClass")]
public class MyClass
{
[DataMember (Name = "id")]
public string Id { get; set; }
[DataMember(Name = "name")]
public string Name { get; set; }
[DataMember(Name = "description")]
public string Description { get; set; }
[DataMember(Name = "parameters")]
public List<object> Parameters { get; set; }
}
Serialization works fine, exactly as I expect:
var myObject = new MyClass();
myObject.Id = "97";
myObject.Name = "Tom Production";
myObject.Parameters = new List<object>();
myObject.Parameters.Add(new { first_parameter_name = "First Parameter Value" });
myObject.Parameters.Add(new { second_parameter_name = "Second Parameter Value" });
string json = JsonConvert.SerializeObject(myObject);
Console.WriteLine(json);
yields the JSON I am looking for, exactly as at the top of this posting.
HOWEVER.
Deserialization does NOT work fine. If it worked the way I hope it to, which would be to create generic types just like I had created, and the following code should work.... but instead it throws a reflection exception:
var myNewObject = JsonConvert.DeserializeObject<MyClass>(json);
foreach (object o in myNewObject.Parameters)
{
Type t = o.GetType();
Console.WriteLine("\tType is {0}", t);
foreach (PropertyInfo pi in t.GetProperties(BindingFlags.Instance | BindingFlags.Public))
{
Console.WriteLine("\t\tName is {0}", pi.Name);
Console.WriteLine("\t\tValue is {0}", pi.GetValue(o, null));
}
}
Instead, I have to write code that is Newtonsoft-specific (ick) to use a kind of fake Newtonsoft reflection:
var myNewObject = JsonConvert.DeserializeObject<MyClass>(json);
foreach (object o in myNewObject.Parameters)
{
var jo = o as JObject;
if (jo != null)
{
foreach (JProperty prop in jo.Properties())
{
Console.WriteLine("\t\tName is {0}", prop.Name);
Console.WriteLine("\t\tValue is {0}", prop.Value);
}
}
}
Is there a way that I can control the Deserializer so that it will generate the proper generic types rather than the JObject type with the JProperties?
Many thanks in advance.
JObjects map most directly to Dictionary<string, object>s, since they're each simply a collection of keys to values. If you know that the value is always a string, you can make it a Dictionary<string, string>.
[DataMember(Name = "parameters")]
public List<Dictionary<string, object>> Parameters { get; set; }
// or
[DataMember(Name = "parameters")]
public List<Dictionary<string, string>> Parameters { get; set; }
// e.g.
var myNewObject = JsonConvert.DeserializeObject<MyClass>(json);
foreach (var dict in myNewObject.Parameters)
{
foreach (var pair in dict)
{
Console.WriteLine("\t\tKey is {0}", pair.Key);
Console.WriteLine("\t\tValue is {0}", pair.Value);
}
}

Convert DataSet with multiple Datatables to Json

I want to convert a dataset which has multiple data-tables within it.
Following is the example,
The dataset X has two data tables A and B
I want the result as follows,
{
"type":"A",
"value":"100",
"details":[
{"name":"John", "age":"45", "gender":"M"},
{"name":"Sebastin", "age":"34", "gender":"M"},
{"name":"Marc", "age":"23", "gender":"M"},
{"name":"Natalia", "age":"34", "gender":"F"}
]
}
Currently I am using Newtonsoft.Json. Is it possible with Newtonsoft.Json?
If not, is it possible with any other .net Json tools?
You can get the JSON you want by implementing a custom JsonConverter for the DataSet like this:
class CustomDataSetConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(DataSet));
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
DataSet x = (DataSet)value;
JObject jObject = new JObject();
DataTable a = x.Tables["A"];
foreach (DataColumn col in a.Columns)
{
jObject.Add(col.Caption.ToLower(), a.Rows[0][col].ToString());
}
JArray jArray = new JArray();
DataTable b = x.Tables["B"];
foreach (DataRow row in b.Rows)
{
JObject jo = new JObject();
foreach (DataColumn col in b.Columns)
{
jo.Add(col.Caption.ToLower(), row[col].ToString());
}
jArray.Add(jo);
}
jObject.Add("details", jArray);
jObject.WriteTo(writer);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
Here is a demo:
class Program
{
static void Main(string[] args)
{
DataSet x = new DataSet();
DataTable a = x.Tables.Add("A");
a.Columns.Add("Type");
a.Columns.Add("Value");
a.Rows.Add("A", "100");
DataTable b = x.Tables.Add("B");
b.Columns.Add("Name");
b.Columns.Add("Age");
b.Columns.Add("Gender");
b.Rows.Add("John", "45", "M");
b.Rows.Add("Sebastian", "34", "M");
b.Rows.Add("Marc", "23", "M");
b.Rows.Add("Natalia", "34", "F");
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.Converters.Add(new CustomDataSetConverter());
settings.Formatting = Formatting.Indented;
string json = JsonConvert.SerializeObject(x, settings);
Console.WriteLine(json);
}
}
Output:
{
"type": "A",
"value": "100",
"details": [
{
"name": "John",
"age": "45",
"gender": "M"
},
{
"name": "Sebastian",
"age": "34",
"gender": "M"
},
{
"name": "Marc",
"age": "23",
"gender": "M"
},
{
"name": "Natalia",
"age": "34",
"gender": "F"
}
]
}
I don't think Json.Net will do this automatically, but you should be able to do this using Typed Datasets.
A typed dataset is the same as the regular DataSet/DataTable classes, but they extend them with properties for each column in the tables and with relations.
Edit:
Alternatively you could build a method that converts the DataTable structures into a class model and then use Json.Net to serialize that. The data model would be simple, with only two classes, and the conversion should also be quite simple to implement.
Edit 2:
An example of how to convert the data table into a class structure:
public class ClassA
{
public string Type { get; set; }
public int Value { get; set; }
public List<ClassB> Details { get; set; }
public static ClassA FromDataRow(DataRow row, IEnumerable<DataRow> relatedRows)
{
var classA = new ClassA
{
Type = (string) row["Type"],
Value = (int) row["Value"],
Details = relatedRows.Select(r => new ClassB
{
Name = (string)r["Name"],
Age = (int)r["Age"],
Gender = (string)r["Gender"]
}).ToList()
};
return classA;
}
}
public class ClassB
{
public string Name { get; set; }
public int Age { get; set; }
public string Gender { get; set; }
}
Here you can run ClassA.FromDataRow() and pass it one row from TableA and a list of rows from TableB and end up with an object structure. This can easily be serialized to the format you want.
Please note that the code must be modified for your use and will probably not compile as it is. But the concept should be clear.
Final Solution for reference
using System.Web.Script.Serialization;
public class ClassA
{
public string Type { get; set; }
public string Value { get; set; }
public List<ClassB> Details { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
DataSet x = new DataSet();
DataTable a = x.Tables.Add("A");
a.Columns.Add("Type");
a.Columns.Add("Value");
a.Rows.Add("A", "100");
DataTable b = x.Tables.Add("B");
b.Columns.Add("Name");
b.Columns.Add("Age");
b.Columns.Add("Gender");
b.Rows.Add("John", "45", "M");
b.Rows.Add("Sebastian", "34", "M");
b.Rows.Add("Marc", "23", "M");
b.Rows.Add("Natalia", "34", "F");
var s = FromDataRow(a.Rows[0], b.AsEnumerable());
JavaScriptSerializer jss = new JavaScriptSerializer();
string output = jss.Serialize(s);
}
public static ClassA FromDataRow(DataRow row, IEnumerable<DataRow> relatedRows)
{
var classA = new ClassA
{
Type = (string)row["Type"],
Value = (string)row["Value"],
Details = relatedRows.Select(r => new ClassB
{
Name = (string)r["Name"],
Age = (string)r["Age"],
Gender = (string)r["Gender"]
}).ToList()
};
return classA;
}
}
public class ClassB
{
public string Name { get; set; }
public string Age { get; set; }
public string Gender { get; set; }
}
Here's a simplified answer:
var datasetList= new List();
var yourChanges= yourDataset.GetChanges();
datasetList.Add(yourChanges);
Once changes are added:
JsonConert.Serialize(datasetList, Formatting.Indented);
this will generated the json for all records.

Categories

Resources