Deserializing JSON Data which contain arrays - c#

I would like to deserialize JSON data which has three keys as follows : Type, Name, Data[]
My Message class which I want my JSON to be serialized into :
class Message
{
public int Type;
public string Name;
public List<KeyValuePair<string, string>> Data;
}
I am able to deserialize Type and Name with this block of code;
Message DeserializedMessage = JsonConvert.DeserializeObject<Message>(myString);
Console.WriteLine("Name: " + DeserializedMessage.Name);
Console.WriteLine("Type: " + DeserializedMessage.Type);
However, I don't have any clue to how to deserialize the key-value pairs in JSON to my List<KeyValuePair<string, string>> Data;
Example JSONs :
{
"Type":"103",
"Name":"Oguzhan",
"Data":
[
{
"InviteTo":"Bahadir"
}
]
}
{
"Type":"104",
"Name":"Oguzhan",
"Data":
[
{
"Game":"Backgammon",
"Duration":"2"
}
]
}

You should change your
public List<KeyValuePair<string, string>> data;
to
public List<Dictionary<string, string>> data;
After that, it's relatively easy:
Message message = JsonConvert.DeserializeObject<Message>(jsonString);
Or, if you would like to use dynamic:
dynamic parsed = JsonConvert.DeserializeObject(jsonString);
Message message = MapToMessage(parsed);
// ...
private Message MapToMessage(dynamic json)
{
return new Message()
{
Type = json.Type,
Name = json.Name,
Data = ((IEnumerable<dynamic>)json.Data).Select(d =>
{
var dic = new Dictionary<string, string>();
foreach (var v in d) dic.Add(v.Name, v.Value.Value);
return dic;
}).ToList()
};
}

Related

How to Pass customfields in c# whmcs

I want to add the customfields in add order api. How to create an array like that: "an array of base64 encoded serialized array of product custom field values"
https://developers.whmcs.com/api-reference/addorder/
I have tried with
Dictionary<string, string> customfiled = new Dictionary<string, string>();
customfiled.Add("1", "Hello");
var tt2 = JsonConvert.SerializeObject(customfiled);
string str =Base64Encode(tt2);
I have created a class that will hold the list of key/values serialized as JSON.
Here is the class:
class ArrayOfBase64Array
{
// serialized JSON
private List<string> list = new List<string>();
public void Add(NameValueCollection collection)
{
foreach(var key in collection.AllKeys)
{
this.Add(key, collection[key]);
}
}
public void Add<T>(string key, T value) {
var dict = new Dictionary<string,T>();
dict.Add(key, value);
var json = JsonConvert.SerializeObject(dict);
list.Add(Base64Encode(json));
}
public string[] ToArray()
{
return list.ToArray();
}
string Base64Encode(string value)
{
return Convert.ToBase64String(Encoding.UTF8.GetBytes(value));
}
}
The AddOrder payload expects a shape that matches this C# class:
// lots of fields omitted for brevity
class AddOrder
{
public string action {get;set;}
public string[] domain {get;set;}
public string[] customfields {get;set;}
}
To create an AddOrder instance with customfields you can now do this:
// create an AddOrder instance
var addOrder = new AddOrder
{
action = "AddOrder",
domain = new [] {"one.example.com", "two.example.com"}
};
// build our customfields collection
var cfarray = new ArrayOfBase64Array();
cfarray.Add("1", "FuBar");
cfarray.Add("2", 999);
cfarray.Add("3", true);
cfarray.Add("4", new JObject(new JProperty("Foo", 4711.42)));
// or if you have a namevaluecollection
var nvc = new NameValueCollection { {"5", "test namevalue 1"}, {"6", "another value"} };
cfarray.Add(nvc);
// store the customfields as an array of strings
addOrder.customfields = cfarray.ToArray();
This is what the data looks like when POST-ed to the server:
{ "action":"AddOrder",
"domain":["one.example.com","two.example.com"],
"customfields":[
"eyIxIjoiRnVCYXIifQ==",
"eyIyIjo5OTl9",
"eyIzIjp0cnVlfQ==",
"eyI0Ijp7IkZvbyI6NDcxMS40Mn19",
"eyI1IjoidGVzdCBuYW1ldmFsdWUgMSJ9",
"eyI2IjoiYW5vdGhlciB2YWx1ZSJ9"]
}
And this is what is in each of the encoded base64 strings:
{"1":"FuBar"}
{"2":999}
{"3":true}
{"4":{"Foo":4711.42}}
{"5":"test namevalue 1"}
{"6":"another value"}

How to deserialize this JSON to C# Class

i'am working with a WebAPI that returns this json from a Request
{
"apps": {
"570": {
"228983": {
"8124929965194586177": "available"
},
"228990": {
"1829726630299308803": "available"
},
"373301": {
"840315559245085162": "available"
},
"373302": {
"688854584180787739": "available"
},
"373303": {
"3675525977143063913": "available"
},
"373305": {
"4435851250675935801": "available"
},
"381451": {
"6984541794104259526": "available"
},
"381452": {
"1442783997179322635": "available"
},
"381453": {
"6878143993063907778": "available"
},
"381454": {
"7824447308675043012": "available"
},
"381455": {
"5681120743357195246": "available"
}
},
"674940": {
"674941": {
"6246860772952658709": "available"
}
}
}
}
It returns A list of AppID (int), that contains another list of DepotID, that it Contains a ManifestID (Key) and if it's aviable or not (Value).
And i want to deserialize to a class to easy work with it, but i can't imagine how to do it. I'am a newbie in C# comming from C/C++
You can use Json.NET which is a popular JSON library for C#. See Deserialize an Object.
Example:
public class MyData
{
public Dictionary<long, Dictionary<long, Dictionary<long, string>>> apps { get; set; }
}
var data = JsonConvert.DeserializeObject<MyData>(json);
// Use 'data.apps'
I'm not sure how much is gained by modeling this as C# classes without property names beyond the "apps" level of your Json, but you could do it like so:
Model your Json with the following classes:
public class AppIds : Dictionary<string, DepotId> { }
public class DepotId : Dictionary<string, ManifestId> { }
public class ManifestId : Dictionary<string, string> { }
And then you can do like so using Newtonsoft.Json
class Program
{
static void Main(string[] args)
{
string jsonPath = #"c:\debug\data.json";
System.IO.Stream s = new System.IO.FileStream(jsonPath,System.IO.FileMode.Open, System.IO.FileAccess.Read);
AppIds data = JsonConvert.DeserializeObject<Dictionary<string, AppIds>>(File.ReadAllText(jsonPath))["apps"];
}
}
You can use the Newtonsoft.Json NuGet package and deserialize your data to a nested dictionary like so:
var data = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, Dictionary<string, Dictionary<string, string>>>>>(File.ReadAllText("Data.json"));
To make sure you got the right data you can run this code to print it out:
foreach (var a in data)
{
Console.WriteLine(a.Key);
foreach (var b in a.Value)
{
Console.WriteLine("\t" + b.Key);
foreach (var c in b.Value)
{
Console.WriteLine("\t\t" + c.Key);
foreach (var d in c.Value)
{
Console.WriteLine("\t\t\t" + d.Key + ": " + d.Value);
}
}
}
}
Not really sure how to deserialize this data to a class since it doesn't have much in the way of property names...

json properties to lower case c#

I'm getting from client json string:
{ "Client": { "Name": "John" } }
but for the further handling I need the following json:
{ "client": { "name": "John" } }
I tried something like that, but it didn't help:
public class LowerCaseNamingStrategy : NamingStrategy
{
protected override string ResolvePropertyName(string name)
{
return name.ToLower();
}
}
and
var settings = new JsonSerializerSettings();
settings.ContractResolver = new DefaultContractResolver { NamingStrategy = new LowerCaseNamingStrategy() };
var json = JsonConvert.DeserializeObject(input.DataJson, settings);
JSON is dynamic object, so I don't know properties are there.
How can I do that with c#? With using Newtonsoft.Json or may be with using Xml.
If I understood you correctly, you need to modify properties in your Json string, but not convert the Json into object.
In this case you can try to parse Json into JObject and replace properties in that object.
private static void ChangePropertiesToLowerCase(JObject jsonObject)
{
foreach (var property in jsonObject.Properties().ToList())
{
if(property.Value.Type == JTokenType.Object)// replace property names in child object
ChangePropertiesToLowerCase((JObject)property.Value);
property.Replace(new JProperty(property.Name.ToLower(),property.Value));// properties are read-only, so we have to replace them
}
}
sample:
var jsonString = #"{ ""Client"": { ""Name"": ""John"" } }";
var jobj = JObject.Parse(jsonString, new JsonLoadSettings());
ChangePropertiesToLowerCase(jobj);
var stringWithLowerCaseProperties = jobj.ToString(Formatting.None);
Try LowercaseContractResolver instead
var settings = new JsonSerializerSettings();
settings.ContractResolver = new LowercaseContractResolver();
var json = JsonConvert.DeserializeObject(input.DataJson, settings);
Extending Anton Semenov answer for cases when JSON can contain an Array of Objects:
private static void ChangePropertiesToLowerCase(JObject jsonObject)
{
foreach (var property in jsonObject.Properties().ToList())
{
if (property.Value.Type == JTokenType.Object) // replace property names in child object
ChangePropertiesToLowerCase((JObject)property.Value);
if (property.Value.Type == JTokenType.Array)
{
var arr = JArray.Parse(property.Value.ToString());
foreach (var pr in arr)
{
ChangePropertiesToLowerCase((JObject)pr);
}
property.Value = arr;
}
property.Replace(new JProperty(property.Name.ToLower(CultureInfo.InvariantCulture), property.Value)); // properties are read-only, so we have to replace them
}
}
All other solutions here modify the original object. Here's an immutable version which returns a new object with lowercase properties:
public static class JsonExtensions
{
public static JToken ToLowerRecursive(this JToken token)
{
if (token is JObject jobj)
return new JObject(jobj.Properties().Select(x => new JProperty(x.Name.ToLowerInvariant(), x.Value.ToLowerRecursive())));
if (token is JArray jarr)
return new JArray(jarr.Select(x => x.ToLowerRecursive()));
return token;
}
}
This is easy way without Regex. Replace every [{ "A] with [{ "a]
var json = "{ \"Client\": { \"Name\": \"John\" } }";
var newJson = string.Empty;
foreach (var w in json.Split(new[] { "{ \"" }, StringSplitOptions.RemoveEmptyEntries))
{
if (w[0] != null)
{
newJson += "{ \"" + (w[0].ToString().ToLower()) + w.Remove(0,1);
}
}
result:
"{ \"client\": { \"name\": \"John\" } }"

C# Json To Dictionary of Objects

I want to take some Json and parse it in to a collection of key/value pairs, but some of the values will be dictionaries themselves. I tried the usual Newtonsoft deserialization. It's close, but not quite right. The end result must be a dictionary, not a strongly typed class.
This is some example Json:
{
"JobNumber": 1010,
"Asset": null,
"JobNotes": [
{
"NoteText": "It's not working.",
"NoteType": "Complaint"
},
{
"NoteText": "Needs to be fixed",
"NoteType": "Job"
}
]
}
This is the code I used to deserialize:
var json = File.ReadAllText(#"c:\temp\job.json");
var result = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
The result is almost correct, but the value of the item with a key of "JobNotes" is just json string. I want the parser to recurse in and deserialise the inner Json to a further dictionary of strings and objects. Is there a way I can do this with the Newtonsoft library? Or, is there another library that will do the trick? Can I hook in to the parsing method to override the functionality at that point in time?
This is a modified version of #DanielKeogh's code. It works well.
class Program
{
static void Main(string[] args)
{
var json = File.ReadAllText(#"c:\temp\job3.json");
var result = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
RecurseDeserialize(result);
}
private static void RecurseDeserialize(Dictionary<string, object> result)
{
//Iterate throgh key/value pairs
foreach (var keyValuePair in result.ToArray())
{
//Check to see if Newtonsoft thinks this is a JArray
var jarray = keyValuePair.Value as JArray;
if (jarray != null)
{
//We have a JArray
//Convert JArray back to json and deserialize to a list of dictionaries
var dictionaries = JsonConvert.DeserializeObject<List<Dictionary<string, object>>>(jarray.ToString());
//Set the result as the dictionary
result[keyValuePair.Key] = dictionaries;
//Iterate throught the dictionaries
foreach (var dictionary in dictionaries)
{
//Recurse
RecurseDeserialize(dictionary);
}
}
}
}
}
This modified Json shows how deep it goes:
{
"JobNumber": 1010,
"Asset": null,
"JobNotes": [
{
"NoteText": "It's not working.",
"NoteType": "Complaint"
},
{
"NoteText": "Needs to be fixed",
"NoteType": "Job",
"JobNoteNotes": [
{
"Something": 1,
"Something2": "Test"
}
]
}
]
}
The result ends three dictionaries deep so that I can get at the "Something" value by key.
This can be done with a little recursion. I'll leave defining IsJson up to you as an academic exercise. :)
Dictionary<string, object> RecursiveDeserialize(string json)
{
var result = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
foreach (var pair in result.ToArray())
{
if(IsJson(pair.Value))
{
result[pair.Key] = RecursiveDeserialize(pair.Value);
}
}
return result;
}
Using this object for json string
public class JobNote
{
public string NoteText { get; set; }
public string NoteType { get; set; }
}
public class ListJob
{
public int JobNumber { get; set; }
public object Asset { get; set; }
public List<JobNote> JobNotes { get; set; }
}
Then you can deserialize it

How to elegantly parse the following text into a dictionary

I have the following text that I need to put into a dictionary. At first sight I thought that it would be very easy but at the end I found myself doing extensive string search and finding sometimes values that break the parser.
"0":
{
"key":"valueWithAnyCharInside",
"key2":"valueWithAnyCharInside",
"key3":"valueWithAnyCharInside"
},
This will map into the following model:
class Item
{
private int id;
private Dictionary<string, string> data;
}
Any ideas? Maybe using regex ...
Your data format is probably a JSON, but you gave only a part of it. I've modified it slightly as:
{"0":
{
"key":"valueWithAnyCharInside",
"key2":"valueWithAnyCharInside",
"key3":"valueWithAnyCharInside"
}
}
now you can parse it as following:
string json = ...; //your json goes here
var serializer = new JavaScriptSerializer();
var parsed = serializer.Deserialize<Dictionary<string, Dictionary<string, string>>>(json);
//printing data
parsed["0"].Select(pair => string.Format( "{0} - {1}", pair.Key, pair.Value))
.ToList()
.ForEach(Console.WriteLine);
prints:
key - valueWithAnyCharInside
key2 - valueWithAnyCharInside
key3 - valueWithAnyCharInside
To get strongly typed List<Item> use next code
List<Item> items = parsed.Select(pair => new Item { Id = int.Parse(pair.Key),
Data = pair.Value})
.ToList();
Where Item is :
class Item
{
public int Id { get; set; }
public Dictionary<string, string> Data {get;set;}
}

Categories

Resources