Deserialize json array of dictionaries in c# - c#

I have an array of dictionaries that I've created in javascript. After serializing to json I get the following string :
"[{\"key\":\"60236\",\"value\":\"1\"},{\"key\":\"60235\",\"value\":\"gdsfgdfsg\"},{\"key\":\"60237\",\"value\":\"1\"}]"
I am having a hard time getting this deserialized into either a list or dictionary in c#.
I've tried:
Dictionary<int, string> values = JsonConvert.DeserializeObject<Dictionary<int, string>>(Model.Json);
but that doesn't work.

There are several ways that you can extract your key/value pairs to construct a dictionary:
var dict = "[{\"key\":\"60236\",\"value\":\"1\"},
{\"key\":\"60235\",\"value\":\"gdsfgdfsg\"},
{\"key\":\"60237\",\"value\":\"1\"}]";
Use List<KeyValuePair<int, string>>
var dictionary = JsonConvert.DeserializeObject<List<KeyValuePair<int, string>>>(dict)
.ToDictionary(x => x.Key, y => y.Value);
Use a custom object that represents your pairs and then create a dictionary from your collection.
var output = JsonConvert.DeserializeObject<List<Temp>>(dict);
var dictionary = output.ToDictionary(x => x.Key, y => y.Value);
public class Temp
{
public int Key { get; set; }
public string Value { get; set; }
}
Finally, if you're uncomfortable with using a custom "throwaway" object just for deserialization, you can take a tiny performance hit and use dynamic instead.
var dictionary = JsonConvert.DeserializeObject<List<dynamic>>(dict)
.ToDictionary (x => (int)x.key, y => (string)y.value);

what i suggest is for try to see what actually your json represent. You can create a class here on Json2CSharp and the use this class/List of this class (depend on whether your json is in the form of array or simple class object).
Just pass type to JsonConvert.DeserializeObject class type part. for example
var output = JsonConvert.DeserializeObject<List<Class>>(json);
In your case is it just an array of Temp class
public class Temp
{
public string key { get; set; }
public string value { get; set; }
}
Sp all you need is :-
var output = JsonConvert.DeserializeObject<List<Temp>>(json);
The you can convert this list to dictionary as suggested in other answer:-
var dictionary = output.ToDictionary(x => x.Key, y => y.Value);
This always help me out. Hope it help you too.

Related

Converting a distinct list to dictionary not working

I'm trying to convert a list of objects to a dictionary using the following code:
var MyDictionary = MyList.Distinct().ToDictionary(i => i.ObjectId, i => i);
I know that a dictionary should not contain duplicate elements, hence the .Distinct(). Yet I still get the following Exception whenever there's a duplicate element:
An item with the same key has already been added.
MyList is a list of MyObject that looks like this:
public class MyObject{
public string ObjectId { get; set; }
public string FName { get; set; }
public string LName { get; set; }
}
Is there a better way to create a dictionary from a list of objects ? or am I doing something wrong?
If you want to compare on the ObjectId, you'll need to pass in a custom comparer to .Distinct(). You can do so like this:
class MyObjectComparer : IEqualityComparer<MyObject>
{
public bool Equals(MyObject x, MyObject y)
{
return x.ObjectId == y.ObjectId;
}
public int GetHashCode(MyObject obj)
{
return obj.ObjectId.GetHashCode();
}
}
var MyDictionary = MyList
.Distinct(new MyObjectComparer())
.ToDictionary(i => i.ObjectId, i => i);
You could use Group by and then select first from the List as below:
var MyDictionary = MyList.GroupBy(i => i.ObjectId, i => i).ToDictionary(i => i.Key, i => i.First());
Distinct works using the objects built in Equals and GetHashCode methods by default but your dictionary works only over the id. You need to pass in a IEqualityComparer in to distinct that does the comparison on Id to test if items are equal or make MyObject implment Equals and GetHashCode and have that compare on the Id.

Iterating over lists and summing and putting result in dictionary

Suppose i have two (could be more) lists of same object having same fields/properties.
Each list represent the same object
Proerpties:
HoursWorked
HoursRate
I want to take iterate and take sum of each field from all lists (could be 2, 3, or so on) and store it in an dictionary with key value pair. e.g HoursWorked:2 and HourseRate:6
Currently, i am able to do it for only one field only (hard coded). I want to make it generic so i can fill dictionary with Key/Value for all fields.
I have defined my dictionary as follow
public Dictionary<string, double> TotalCount { get; set; }
Linq Query:
Dictionary<string, double> totalCount = records
.GroupBy(x => records)
.ToDictionary(x => Convert.ToString("HoursWorked"), x => x.Where(y => y.HoursWorked != null).Sum(y => y.HoursWorked).Value);
Any help on this?
Sample Data:
Input
report =
{
[HoursWorked: 1.0, HoursRate:10],
[HoursWork:2.0, HoursRate:15]
}
Expected Output
Dictioary = {Key:HoursWorked Value: 3.0,Key:HoursRate Value:25}
Dictionary<string, double> dictionary = new[] { "HoursWorked", "HoursRate" }
.ToDictionary(k => k, v => collections
.SelectMany(x => x)
.Sum(y => (double)y.GetType().GetProperty(v).GetValue(y)));
Where 'collections' is your collection of lists.
Obviously totally type unsafe and will fall down very easily!
I would argue that a much better pattern for this, as opposed to using reflection, would be to write a method or interface that will return the correct double value given the string key.
class someObject
{
public int workingHours { get; set; }
public int hourRate { get; set; }
}
You can create a common list from all list.
List<SomeObject> lst = new List<SomeObject>();
lst.AddRange(Oldlst1);
lst.AddRange(Oldlst2);
Then you can group by based on hour rate.
var n = lst.GroupBy(x=>x.hourRate);
And then you can create a dictionary.
var m=n.ToDictionary(x=>x.Key, x=>x.Sum(y=>y.workingHours));
Here in m you will get hourRate and in value you will get sum of working hour.

How to get a list of dynamic object properties in c#

I have JSON object, something like this, and its dynamic, jsonInput=
{
"CONTRATE":80,
"SALINC":30,
"RETAGE":67,
"MARSTATUS":"single",
"SPOUSEDOB":"1970-01-01",
"VIEWOPTION":"pension"
}
I am converting it into .NET dynamic object using Newtonsoft.Json converter:
var jsonDynamic = JsonConvert.DeserializeObject<dynamic>(jsonInput);
Now I have dynamic jsonDynamic .NET object.
How can I get it's properties now?
These should be jsonDynamic.CONTRATE, jsonDynamic.SALINC etc...
How can I get the names of these properties from jsonDynamic?
Thanks.
var jobj = JObject.Parse(jsonInput);
dynamic jsonDynamic = jobj;
var dict = jobj.Children()
.OfType<JProperty>()
.ToDictionary(x => x.Name, x => x.Value);
int c = (int)dict["CONTRATE"];
or if you want only property names
var propNames = jobj.Children()
.OfType<JProperty>()
.Select(x => x.Name)
.ToList();
You could create a class that would represent the json you want to deserialize, like below:
public class ClassName
{
public int Contrate { get; set; }
public int Salinc { get; set; }
// Here you will place the rest of your properties.
}
and then just use this:
var jsonDynamic = JsonConvert.DeserializeObject<ClassName>(jsonInput);
This way you will avoid making use of a dynamic object.
You should deserialize into a Dictionary and then you can loop through the Keys to get the property names
Dictionary<string, string> values = JsonConvert.DeserializeObject<Dictionary<string, string>>(jsonInput);
You can access the values.Keys to get the property names then.

Converting complex object to dictionary<string,string>

I need to convert a dto object class like this :
public class ComplexDto
{
public ComplexDto()
{
ListIds = new List<ListIdsDto>();
}
public string Propertie1 { get; set; }
public string Propertie2 { get; set; }
public IList<int> ListIds { get; set; }
}
to a dictionary<string,string>.
This is just some class example, this class will be used as json object like this:
{"Propertie1":"ss","Propertie2":"","ListIds":[1,2,3]}
I need to pass this object to a FormUrlEncodedContent(dictionary) as dictionary of strings.
I have this :
var data = new Dictionary<string, string>();
data[string.Empty] = ComplexDto.ToJson();
And I would like to transform the ComplexDto.ToJson() or the ComplexDto object to a Dictionary string, string.
Any Ideas ?
Assuming that you have a collection with some ComplexDto instances like:
List<ComplexDto> complexDtoList = ...;
and you expect that there are duplicate keys which would cause an exception(otherwise you could have used a dictionary in the first place).
You can use Enumerable.GroupBy to get unique keys. Then you have to decide what you want to do with the 1-n Propertie2-strings per group. One way is to use String.Join to concat all with a separator:
Dictionary<string, string> result = complexDtoList
.GroupBy(dto => dto.Propertie1)
.ToDictionary(
p1Group => p1Group.Key,
p1Group => string.Join(",", p1Group.Select(dto => dto.Propertie2)));
You could also build a Dictionary<string, List<string>> and use p1Group.Select(dto => dto.Propertie2).ToList() as value.

Convert Dictionary<string, object> to a collection of objects with key

Is there a way to convert Dictionary<string, obj> to collection of objects such that each single object in the collection includes the key as another property
Here is the class def for obj
class someclass
{
string property1;
string property2;
}
After conversion, I am expecting each object in the collection to be like
obj.property1
obj.property2
obj.Key
I have been struggling with this since along time and I seek some help. any ideas?
thanks in advance.
Something like
var myCollection = from de in myDictionary
select new
{
de.Value.property1,
de.Value.property2,
de.Key
}.ToList(); // or .ToArray()
should do the trick.
That will return a List of a new anonymous type with the properties you requested.
You could also(in addition to the anonymous type apporach) use a List<Tuple<string, string, string>>:
var list= dictionary
.Select(kv => Tuple.Create(kv.Value.property1, kv.Value.property2, kv.Key))
.ToList();
foreach(var item in list)
{
Console.WriteLine("property1:{0 property2:{1} key:{2}"
, item.Item1
, item.Item2
, item.Item3);
}
The advantage over an anonymous type is that you can return the Tuple easily from a method.
Edit: A third option(my favorite) is simply to create instances of a class that you've declared somewhere. That's the ideal way. I don't know why i thought that you want a class "on the fly".
class someOtherClass
{
public string property1{ get; set; };
public string property2{ get; set; };
public string Key{ get; set; };
}
List<someOtherClass> objects = dictionary
.Select(kv => new someOtherClass(){
property1 = kv.Value.property1,
property2 = kv.Value.property2,
Key = kv.Key
})
.ToList();
You may use anonymous type if you don't want to store the result like this:
In case you just wana use it as datasource for example.
var res = myDictionary.Select(pair => new { pair.Key, pair.Value.Property1, pair.Value.Property2 });
The other answers are good, so this is just a supplement.
You could use arrays of Length three:
var arrays = myDictionary
.Select(kv => new[] { kv.Value.property1, kv.Value.property2, kv.Key, });
Or you could write a new class
class SomeclassAndKey
{
public string property1;
public string property1;
public string Key;
}
and then say
var someclassAndKeys = myDictionary
.Select(kv => new SomeclassAndKey { property1 = kv.Value.property1, property2 = kv.Value.property2, Key = kv.Key, });
In each case you could append .ToList() if you wanted not to defer enumeration and get a full List<> out.

Categories