Convert JSON to C# Object array - c#

This is my JSON object and C# class
{
"header": [
"id",
"name",
"address"
],
"rows": [
[
"ee1e9edd-a06b-3f8c-97f1-62878d04540d",
"John Doe",
"test address 1234"
],
[
"ee1e9edd-a06b-3f8c-97f1-62878d04540d",
"Jane Rock",
"test address 12345"
]
]
}
C# class
public class Student
{
public string id { get; set; }
public string name { get; set; }
public string address { get; set; }
}
is that possible to convert JSON into C# class list using JsonConvert or any other library without using loop?

The conversion is pretty straightforward with Json.NET's JObject and Linq:
var students = JObject.Parse(json)["rows"] // Parse the JSON and get the "rows" property
.Values<string[]>() // Get the property values as string arrays
.Select(arr => new Student() { // Convert each string array to a Student object
id = arr[0],
name = arr[1],
address = arr[2]
}).ToList(); // Convert the IEnumerable<Student> to a List<Student>

If you have multiple json definitions that have the same headers/rows layout you could use this custom converter for the Newtonsoft.Json library.
Usage:
var input = "{\"header\":[\"id\",\"name\",\"address\"],\"rows\":[[\"ee1e9edd-a06b-3f8c-97f1-62878d04540d\",\"John Doe\",\"test address 1234\"],[\"ee1e9edd-a06b-3f8c-97f1-62878d04540d\",\"Jane Rock\",\"test address 12345\"]]}";
var studens = JsonConvert.DeserializeObject<List<Student>>(input, new MyConverter<Student>());
foreach (var student in students)
{
Console.WriteLine(student.name);
}
The converter looks like this:
public class MyConverter<T> : JsonConverter where T : new()
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
// Not required.
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
reader.Read(); // Read StartObject token.
var mapping = GetMapping(reader);
var result = GetObjects(reader, mapping);
reader.Read(); // Read EndObject token.
return result;
}
private Dictionary<int, string> GetMapping(JsonReader reader)
{
Dictionary<int, string> mapping = new();
// Advance to the first header definition.
reader.Read(); // Read PropertyName token (should be 'headers').
reader.Read(); // Read StartArray token.
int index = 0;
do
{
index++;
mapping[index] = reader.Value.ToString();
reader.Read(); // Advance to next array element.
}
while(reader.TokenType != JsonToken.EndArray);
reader.Read(); // Read EndArray token.
return mapping;
}
private List<T> GetObjects(JsonReader reader, Dictionary<int, string> mapping)
{
List<T> result = new();
// Advance to the first row definition.
reader.Read(); // Read PropertyName token (should be 'rows').
reader.Read(); // Read StartArray token.
do
{
result.Add(GetObject(reader, mapping));
}
while(reader.TokenType != JsonToken.EndArray);
reader.Read(); // Read EndArray token.
return result;
}
private T GetObject(JsonReader reader, Dictionary<int, string> mapping)
{
// The object is an array in json.
reader.Read(); // Read StartArray token.
int index = 0;
T result = new();
do
{
index++;
var propertyToFind = mapping[index];
// Set the value to a property with matching name if it exists.
result.GetType().GetProperty(propertyToFind)?.SetValue(result, reader.Value);
reader.Read(); // Advance to next array element.
}
while(reader.TokenType != JsonToken.EndArray);
reader.Read(); // Read EndArray token.
return result;
}
public override bool CanConvert(Type objectType)
{
return true;
}
}

Related

How to deserialize JSON containing an array of objects with a single property name and value each into a c# model?

I have the following model:
public class UserPtr
{
public int my_var1 { get; set; }
public int my_var2 { get; set; }
public int my_var3 { get; set; }
public int my_var4 { get; set; }
}
And some API response JSON which is:
[
{
"name": "my_var1",
"ptr": 1 // "Value_my_var1"
},
{
"name": "my_var2",
"ptr": 2 // "Value_my_var2"
},
{
"name": "my_var3",
"ptr": 3 // "Value_my_var3"
},
{
"name": "my_var4",
"ptr": 4 // "Value_my_var4"
}
]
I want to set my_var1 = Value_my_var1, my_var2 = Value_my_var2, my_var3 = Value_my_var3
Normally I would use:
JsonConvert.DeserializeObject<UserPtr>(strJson);
But when I do, I get the following exception:
Newtonsoft.Json.JsonSerializationException: Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'UserPtr' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.
To fix this error either change the JSON to a JSON object (e.g. {"name":"value"}) or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array.
How can I deserialize this array of objects containing property names and values into my model?
You would like to serialize your model as an array of objects containing property names and property values, where the names and values come from the "default" JSON serialization for your model. You can do this with a custom generic JsonConverter<T> that translates between the default serialization and the array serialization.
By default, your UserPtr model should be serialized as follows:
{
"my_var1": 1,
"my_var2": 2,
"my_var3": 2,
"my_var4": 4
}
But instead, you are receiving an array of objects containing single name/value pairs as shown in your question, where the names correspond to your model's property names. You would like to bind this array to your model. To accomplish this, you can create a generic converter similar to the one from Deserialize JSON from a Sharepoint 2013 search result into a list of MyClass as follows:
public class NamePtrPropertyArrayConverter<T> : JsonConverter<T> where T : class, new()
{
struct NamePtrDTO
{
public string name;
public object ptr;
}
public override void WriteJson(JsonWriter writer, T value, JsonSerializer serializer)
{
var obj = (JObject)JsonExtensions.DefaultFromObject(serializer, value);
serializer.Serialize(writer, obj.Properties().Select(p => new NamePtrDTO { name = p.Name, ptr = p.Value }));
}
public override T ReadJson(JsonReader reader, Type objectType, T existingValue, bool hasExistingValue, JsonSerializer serializer)
{
if (reader.MoveToContentAndAssert().TokenType == JsonToken.Null)
return null;
var array = serializer.Deserialize<List<NamePtrDTO>>(reader);
var obj = new JObject(array.Select(i => new JProperty(i.name, i.ptr)));
existingValue = existingValue ?? (T)serializer.ContractResolver.ResolveContract(objectType).DefaultCreator();
using (var subReader = obj.CreateReader())
serializer.Populate(subReader, existingValue);
return existingValue;
}
}
public static partial class JsonExtensions
{
public static JsonReader MoveToContentAndAssert(this JsonReader reader)
{
if (reader == null)
throw new ArgumentNullException();
if (reader.TokenType == JsonToken.None) // Skip past beginning of stream.
reader.ReadAndAssert();
while (reader.TokenType == JsonToken.Comment) // Skip past comments.
reader.ReadAndAssert();
return reader;
}
public static JsonReader ReadAndAssert(this JsonReader reader)
{
if (reader == null)
throw new ArgumentNullException();
if (!reader.Read())
throw new JsonReaderException("Unexpected end of JSON stream.");
return reader;
}
// DefaultFromObject() taken from this answer https://stackoverflow.com/a/29720068/3744182
// By https://stackoverflow.com/users/3744182/dbc
// To https://stackoverflow.com/questions/29719509/json-net-throws-stackoverflowexception-when-using-jsonconvert
public static JToken DefaultFromObject(this JsonSerializer serializer, object value)
{
if (value == null)
return JValue.CreateNull();
var dto = Activator.CreateInstance(typeof(DefaultSerializationDTO<>).MakeGenericType(value.GetType()), value);
var root = JObject.FromObject(dto, serializer);
return root["Value"].RemoveFromLowestPossibleParent() ?? JValue.CreateNull();
}
public static JToken RemoveFromLowestPossibleParent(this JToken node)
{
if (node == null)
return null;
// If the parent is a JProperty, remove that instead of the token itself.
var contained = node.Parent is JProperty ? node.Parent : node;
contained.Remove();
// Also detach the node from its immediate containing property -- Remove() does not do this even though it seems like it should
if (contained is JProperty)
((JProperty)node.Parent).Value = null;
return node;
}
interface IHasValue
{
object GetValue();
}
[JsonObject(NamingStrategyType = typeof(DefaultNamingStrategy), IsReference = false)]
class DefaultSerializationDTO<T> : IHasValue
{
public DefaultSerializationDTO(T value) => this.Value = value;
public DefaultSerializationDTO() { }
[JsonConverter(typeof(NoConverter)), JsonProperty(ReferenceLoopHandling = ReferenceLoopHandling.Serialize)]
public T Value { get; set; }
object IHasValue.GetValue() => Value;
}
}
public class NoConverter : JsonConverter
{
// NoConverter taken from this answer https://stackoverflow.com/a/39739105/3744182
// By https://stackoverflow.com/users/3744182/dbc
// To https://stackoverflow.com/questions/39738714/selectively-use-default-json-converter
public override bool CanConvert(Type objectType) { throw new NotImplementedException(); /* This converter should only be applied via attributes */ }
public override bool CanRead => false;
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) => throw new NotImplementedException();
public override bool CanWrite => false;
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) => throw new NotImplementedException();
}
Then, either deserialize by adding the converter to JsonSerializerSettings.Converters:
var settings = new JsonSerializerSettings
{
Converters = { new NamePtrPropertyArrayConverter<UserPtr>() },
};
var model = JsonConvert.DeserializeObject<UserPtr>(strJson, settings);
Or apply the converter directly to your model as follows:
[JsonConverter(typeof(NamePtrPropertyArrayConverter<UserPtr>))]
public class UserPtr
{
// Contents unchanged
}
Demo fiddle here.

JSON to C#, deserialize property that is either object or array

I have an issue with handling JSON data from an api that I use in my application. The problem is that the JSON contains some properties that are an object when there is an item, and become an array when there are more items. So that's a structure like this:
[
{
"MyObj": {
"Foo": "Bar"
}
},
{
"MyObj": [
{
"Foo": "Bar1"
},
{
"Foo": "Bar2"
}
]
}
]
I've tried several JSON to C# converters, some of them generate a property of type object, the quicktype.io converter generates this:
public class Example
{
[JsonProperty("MyObj")]
public MyObjUnion MyObj { get; set; }
}
public partial class MyObjElement
{
[JsonProperty("Foo")]
public string Foo { get; set; }
}
public struct MyObjUnion
{
public MyObjElement MyObjElement;
public MyObjElement[] MyObjElementArray;
public static implicit operator MyObjUnion(MyObjElement MyObjElement) => new MyObjUnion { MyObjElement = MyObjElement };
public static implicit operator MyObjUnion(MyObjElement[] MyObjElementArray) => new MyObjUnion { MyObjElementArray = MyObjElementArray };
}
internal class MyObjUnionConverter : JsonConverter
{
public override bool CanConvert(Type t) => t == typeof(MyObjUnion) || t == typeof(MyObjUnion?);
public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer)
{
switch (reader.TokenType)
{
case JsonToken.StartObject:
var objectValue = serializer.Deserialize<MyObjElement>(reader);
return new MyObjUnion { MyObjElement = objectValue };
case JsonToken.StartArray:
var arrayValue = serializer.Deserialize<MyObjElement[]>(reader);
return new MyObjUnion { MyObjElementArray = arrayValue };
}
throw new Exception("Cannot unmarshal type MyObjUnion");
}
public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer)
{
var value = (MyObjUnion)untypedValue;
if (value.MyObjElementArray != null)
{
serializer.Serialize(writer, value.MyObjElementArray);
return;
}
if (value.MyObjElement != null)
{
serializer.Serialize(writer, value.MyObjElement);
return;
}
throw new Exception("Cannot marshal type MyObjUnion");
}
public static readonly MyObjUnionConverter Singleton = new MyObjUnionConverter();
}
Although this does work correctly, it's still a bit cumbersome because to get the data you always need to check if it's in the MyObjElement or MyObjElementArray class.
So the question is if there are other, more elegant ways to solve this issue. (Other than changing the API output, which is not mine)
If you know the data structure before hand, I would create a custom data model for the Json file and then deserialise it like so:
CurrencyExchangeRates deserialisedData = JsonConvert.DeserializeObject<CurrencyExchangeRates>(savedData);
foreach (CurrentRate value in deserialisedData.ExchangeRates)
{
rate.ExchangeRates.Add(new CurrentRate { Rate = value.Rate, Timestamp = value.Timestamp });
}
This is how I did that in an application. Hope this helps a little.
You can check and cast each object in your JSON depending the type of object.
For example consider using Newtonsoft.Json library for JSON parsing, you can do the following:
// considering your JSON string
string jsonString = "[{'MyObj':{'Foo':'Bar'}},{'MyObj':[{'Foo':'Bar1'},{'Foo':'Bar2'}]}]";
// parse your JSON into JTokens
var tokens = JToken.Parse(jsonString);
// iterate through all the tokens
foreach (var token in tokens)
{
// your token is a grand child
JToken myObj = token.First.First;
// check if the grand child is array
if (myObj is JArray)
{
// cast the grand child token into MyObj list or array object
IEnumerable<MyObj> objList = myObj.ToObject<List<MyObj>>();
Console.WriteLine("converted to MyObj Array");
}
else if (myObj is JObject) // else if its a non array item
{
// cast the grand child token into MyObj object
MyObj obj = myObj.ToObject<MyObj>();
Console.WriteLine("converted to MyObj");
}
}
// your MyObj Type will look like this:
public class MyObj
{
public string Foo { get; set; }
}

Deserializing JSON into a C# class with dynamic field names

My question is very similar to this one. I tried adapting their solution to fit my needs but can't seem to figure out the solution for my JSON.
Here is an example of the JSON:
{
"0fea8f8a-4169-495d-8307-50bc333fd87d": {
"serviceId": "4cb9125a-1eaa-4bd4-a473-cfccec0f3c63"
},
"0564d078-94f5-4f97-8398-b9f58a51f70b": {
"serviceId": "00000000-0000-0000-0000-000000000000"
},
"f9a165d2-967d-4733-8599-1074270dae2e": {
"serviceId": "00000000-0000-0000-0000-000000000000"
},
"86ccdsbf-e7ad-4851-93ff-6ec817469c1e": {
"serviceId": "00000000-0000-0000-0000-000000000000"
}
}
As you can see, it is a series (not an array) of
Id_1 : {serviceId: Id_2}
I think this can most simply be represented in a C# class as something like this: List<KeyValuePair<string, string>>, basically a List of <Id_1, Id_2>, but I'm open to alternatives.
Here is my attempt at a solution based on the linked post above:
class PolicyMetadata
{
[JsonConverter(typeof(MetadataConverter))]
public KeyValuePair<string,string>[] idPairs { get; set; }
}
class MetadataConverter : JsonConverter
{
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
// deserialize as object
var pairs = serializer.Deserialize<JObject>(reader);
var result = new List<KeyValuePair<string, string>>();
// create an array out of the properties
foreach (JProperty property in pairs.Properties())
{
var pair = property.Value.ToObject<KeyValuePair<string, string>>();
result.Add(pair);
}
return result.ToArray();
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override bool CanConvert(Type objectType)
{
return objectType == typeof(KeyValuePair<string, string>[]);
}
}
And I call it here:
var response = JsonConvert.DeserializeObject<PolicyMetadata>(content);
But this resuts in a null value, so I am definitely doing something wrong. I tried placing breakpoints and print statements throughout the ReadJson method, but they were never triggered, so I'm not sure if that code is actually running.
Model:
public class Service
{
public string ServiceId { get; set; }
}
Use dictionary:
static void Main()
{
string json = #"
{
""0fea8f8a-4169-495d-8307-50bc333fd87d"": {
""serviceId"": ""4cb9125a-1eaa-4bd4-a473-cfccec0f3c63""
},
""0564d078-94f5-4f97-8398-b9f58a51f70b"": {
""serviceId"": ""00000000-0000-0000-0000-000000000000""
},
""f9a165d2-967d-4733-8599-1074270dae2e"": {
""serviceId"": ""00000000-0000-0000-0000-000000000000""
},
""86ccdsbf-e7ad-4851-93ff-6ec817469c1e"": {
""serviceId"": ""00000000-0000-0000-0000-000000000000""
}
}";
var result = JsonConvert.DeserializeObject<Dictionary<string, Service>>(json);
foreach (var pair in result)
{
Console.WriteLine("Key: " + pair.Key + " ServiceId: " + pair.Value.ServiceId);
}
}

JSON.net: converting 1 object into 2 separate arrays without a parent – with JsonConverter

JSON.net: How to convert/split 1 object into 2 separate arrays without a parent node with JsonConverter?
JSON – actual:
{"Name":"Bus",
"Type":"Vehicle",
"SymCollection":[
{"ids":[0,1]},
{"weights":[100,50]}
]}
JSON – expected:
{"Name":"Bus",
"Type":"Vehicle",
"ids":[0,1],
"weights":[100,50]
}
C# – source object (cannot be changed):
class TestClass
{
public string Name;
public string Type;
public SymCollection SymCollection;
}
[JsonConverter(typeof(SymCollectionConverter))]
class SymCollection
{
public int[] Ids;
public int[] Weights;
}
C# – JsonConverter. How do I change it?
class SymCollectionConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
SymCollection inputContainer = (SymCollection)value;
// Need to delete next line – do not need any parent node.
writer.WriteStartArray();
writer.WriteStartObject();
writer.WritePropertyName("ids");
writer.WriteStartArray();
foreach (var id in inputContainer.Ids)
{
writer.WriteValue(id);
}
writer.WriteEndArray();
writer.WriteEndObject();
writer.WriteStartObject();
writer.WritePropertyName("weights");
writer.WriteStartArray();
foreach (var weight in inputContainer.Weights)
{
writer.WriteValue(weight);
}
writer.WriteEndArray();
writer.WriteEndObject();
// So, and delete next line too.
writer.WriteEndArray();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override bool CanConvert(Type objectType)
{
return typeof(SymCollection) == objectType;
}
}
Unfortunately, the structure of the TestClass and SymCollection cannot be changed.
UPDATE 1: one of the possible solutions, as proposed by Pavel Anikhouski, partially handmade without JsonConverter:
class TestClass
{
public string Name;
public string Type;
[JsonIgnore]// Ignore and process it manually.
public SymCollection SymCollection;
public string ToJson()
{
// --> MAIN ATTENTION HERE <
// Create JSON without SymCollection.
var resultJObject = JObject.FromObject(this);
// Add missing IDs and weights.
var symbolIdsAndWeights = SymCollection.GetIdsAndWeightsJTokens();
resultJObject.Add(symbolIdsAndWeights.ids);
resultJObject.Add(symbolIdsAndWeights.weights);
// Convert to string.
string resultJson = resultJObject.ToString(Formatting.None);
return resultJson;
}
}
[JsonConverter(typeof(SymCollectionConverter))]
class SymCollection
{
public int[] Ids;
public int[] Weights;
public (JToken ids, JToken weights) GetIdsAndWeightsJTokens()
{
JTokenWriter idsWriter = new JTokenWriter();
idsWriter.WriteStartObject();
idsWriter.WritePropertyName("ids");
idsWriter.WriteStartArray();
foreach (var id in Ids)
{
idsWriter.WriteValue(id);
}
idsWriter.WriteEndArray();
idsWriter.WriteEndObject();
JTokenWriter weightsWriter = new JTokenWriter();
weightsWriter.WriteStartObject();
weightsWriter.WritePropertyName("weights");
weightsWriter.WriteStartArray();
foreach (var weight in Weights)
{
weightsWriter.WriteValue(weight);
}
weightsWriter.WriteEndArray();
weightsWriter.WriteEndObject();
return (idsWriter.Token.First, weightsWriter.Token.First);
}
}
And usage as:
TestClass testObject = new TestClass();
string resultJsonStr = testObject.ToJson();
Console.WriteLine(resultJsonStr);
You can try to rewrite your json using Json.Linq. Parse value to JObject, then enumerate SymCollection items (since it's an array), then go through every item properties and add each property to the parent, using Name and Value of JProperty. Finally remove SymCollection token
var jObject = JObject.Parse(json);
foreach (JObject item in jObject["SymCollection"])
{
foreach (var property in item.Properties())
{
jObject.Add(property.Name, property.Value);
}
}
jObject.Remove("SymCollection");
var result = jObject.ToString();
Maybe, the inner for loop is redundant, you can get only a first property of every SymCollection item without using a loop (if you sure of that).
The code above produces the following output
{
"Name": "Bus",
"Type": "Vehicle",
"ids": [
0,
1
],
"weights": [
100,
50
]
}

Json.NET - Default deserialization behavior for a single property in CustomCreationConverter

In the following scenario, how do I get CrazyItemConverter to carry on as usual when it encounters a JSON property that exists in the type I'm deserializing to?
I have some JSON that looks like this:
{
"Item":{
"Name":"Apple",
"Id":null,
"Size":5,
"Quality":2
}
}
The JSON gets deserialized into a class that looks a whole lot like this:
[JsonConverter(typeof(CrazyItemConverter))]
public class Item
{
[JsonConverter(typeof(CrazyStringConverter))]
public string Name { get; set; }
public Guid? Id { get; set; }
[JsonIgnore]
public Dictionary<string, object> CustomFields
{
get
{
if (_customFields == null)
_customFields = new Dictionary<string, object>();
return _customFields;
}
}
...
}
CrazyItemConverter populates the values of the known properties and puts the unknown properties in CustomFields. The ReadJson in it looks like this:
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var outputObject = Create(objectType);
var objProps = objectType.GetProperties().Select(p => p.Name).ToArray();
while (reader.Read())
{
if (reader.TokenType == JsonToken.PropertyName)
{
string propertyName = reader.Value.ToString();
if (reader.Read())
{
if (objProps.Contains(propertyName))
{
// No idea :(
// serializer.Populate(reader, outputObject);
}
else
{
outputObject.AddProperty(propertyName, reader.Value);
}
}
}
}
return outputObject;
}
During deserialization, when CrazyItemConverter encounters a known property, I want it to act as it normally would. Meaning, respecting the [JsonConverter(typeof(CrazyStringConverter))] for Name.
I was using the code below to set the known properties but, it throws exceptions on nullables and doesn't respect my other JsonConverters.
PropertyInfo pi = outputObject.GetType().GetProperty(readerValue, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
var convertedValue = Convert.ChangeType(reader.Value, pi.PropertyType);
pi.SetValue(outputObject, convertedValue, null);
Any ideas?
UPDATE: I've learned that serializer.Populate(reader, outputObject); is how to deserialize the whole thing but it doesn't seem to work if you want default functionality on a property-by-property basis.
If I'm understanding correctly, your CrazyItemConverter exists so that you can deserialize known properties in the JSON to strongly-typed properties, while still preserving "extra" fields that may be in the JSON into dictionary.
It turns out that Json.Net already has this feature built in (since 5.0 release 5), so you don't need a crazy converter. Instead, you just need to mark your dictionary with the [JsonExtensionData] attribute. (See the author's blog for more information.)
So your Item class would look like this:
public class Item
{
[JsonConverter(typeof(CrazyStringConverter))]
public string Name { get; set; }
public Guid? Id { get; set; }
[JsonExtensionData]
public Dictionary<string, object> CustomFields
{
get
{
if (_customFields == null)
_customFields = new Dictionary<string, object>();
return _customFields;
}
private set
{
_customFields = value;
}
}
private Dictionary<string, object> _customFields;
}
Then you can just deserialize it as normal. Demo:
class Program
{
static void Main(string[] args)
{
string json = #"
{
""Item"":
{
""Name"":""Apple"",
""Id"":""4b7e9f9f-7a30-4f79-8e47-8b50ea26ddac"",
""Size"":5,
""Quality"":2
}
}";
Item item = JsonConvert.DeserializeObject<Wrapper>(json).Item;
Console.WriteLine("Name: " + item.Name);
Console.WriteLine("Id: " + item.Id);
foreach (KeyValuePair<string, object> kvp in item.CustomFields)
{
Console.WriteLine(kvp.Key + ": " + kvp.Value);
}
}
}
public class Wrapper
{
public Item Item { get; set; }
}
class CrazyStringConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(string);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JToken token = JToken.Load(reader);
// Reverse the string just for fun
return new string(token.ToString().Reverse().ToArray());
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
Output:
Name: elppA
Id: 4b7e9f9f-7a30-4f79-8e47-8b50ea26ddac
Size: 5
Quality: 2

Categories

Resources