C# deserialize json into dictionary and reverse KV - c#

I am trying to deserialize json and reverse the key/value with the least amount of complexity. I have an input json that looks like:
{
"1":"apple",
"2":"banana",
"3":"orange",
"4":"grape"
}
And want to serialize this into a Dictionary<string,string>, but reverse the dictionary so the fruit is the key and the integers are the value. Any way to achieve that with Newtonsoft.Json?
var obj = JsonConvert.DeserializeObject<Dictionary<string,string>>(json);
// obj.Keys = { "1", "2", "3" }, but I want them to be { "apple", "banana", ... }

The least complex way would be to just create another dictionary from the one you've deserialised:
JsonConvert.DeserializeObject<Dictionary<string,string>>(json)
.ToDictionary(x => x.Value, x => x.Key);

var obj = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
Dictionary<string, string> temp = new Dictionary<string, string>();
Parallel.ForEach(obj, (item)=> {
temp.Add(item.Value, item.Key);
});
This is the simplified way you can achieve this .

Related

Dictionary of two different type and convert as JSON

I have a Json file write as follow :
{
"KeyString1": "ValueString1",
"KeyListOfDict": [
{
"KeyString2": "ValueString2",
"KeyDict2": {
"KeyString3": "ValueString3"
}
},
{
"KeyString4": "ValueString4",
"KeyDict2": {
"KeyString5": "ValueString5"
}
}
]
}
I need to access "ValueString3" and "ValueString5" but I can't manage to Deserialize in a Dictionary.
dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
Because of the several value type in the dictinary I don't know to make the thing work.
Can you help to find a way to use this Json file ?
You can try with JObject
string json = File.ReadAllText(path);
var resultToDict = JObject.Parse(json)["KeyListOfDict"]
.Select(p => (((JProperty)p["KeyDict2"].Children().First()).Name, ((JProperty)p["KeyDict2"].Children().First()).Value))
.ToDictionary(x => x.Name, x => x.Value.ToString());
JavaScriptSerializer jss = new JavaScriptSerializer();
jss.Deserialize<dynamic>(json);
the result you can able access with the property name.

How to get the TValue List<> of Dictionary<>

I have a Dictionary<> that's set up as follows:
Dictionary<int, List<string>> srt = new Dictionary<int, List<string>>();
and I would like to access a specific string in the List<string> (which is the TValue in the Dictionary<>
).
For example -> Given: Dictionary<1, {"string1", "string2", "string3"}>, how can I access "string2", and only "string2" specifically.
I hope the question was clear enough to understand. If it wasn't, tell me what I need to clarify.
Thanks!
Is this what you want?
Dictionary<int, List<string>> dict = new Dictionary<int, List<string>>();
dict .Add(1, new List<string> { "Hello", "World" });
string result = fileList[1][1]; //Will output "World"
try this:
var res = srt[1][0]; //"string1"
First index is a key and second index refers to list element
You can use this
var concreteValue = str.Values.SelectMany(l => l.Where(v => v.Equals("string2")))
.FirstOrDefault();
It's pretty simple actually. Access by key to the specific list then you can treat it as an array. The syntax would be srt[key][index]
Which means to access string2 specifically you need write as var b = srt[1][1]; here b will have string2

How to write Dictionary contents to a textfile

I have declared a dictionary like below--
Dictionary<int, string> dic = new Dictionary<int, string>()
{
{977,"String1"},
{1021,"String2"},
{784,"String3"},
{801, "String4"}
};
In my textfile value will be contain like this-
977,"String1",
1021,"String2",
784,"String3",
801, "String4"
I want to store above dictionary keys and values manually in a text file and want to access like dictionary by for loop.
Like this--
foreach (KeyValuePair<int, string> pair in dic)
{
if (pair.Key == any_integer_value_to_compare)
{
Console.WriteLine(pair.Value);
}
}
How can I do that??
You can use serialization/De-serialization to store and retrieve dictionary data from a XML file. It's better method as far as performance is concerned.
Here is how you can implement that:
Declare class Item:
public class item
{
[XmlAttribute]
public int id;
[XmlAttribute]
public string value;
}
Your Dictionary:
Dictionary<int, string> dict = new Dictionary<int, string>()
{
{977,"String1"},
{1021,"String2"},
{784,"String3"},
{801, "String4"}
};
Create Serializer object:
XmlSerializer serializer = new XmlSerializer(typeof(item[]),newXmlRootAttribute() { ElementName = "items" });
Serialization:
serializer.Serialize(stream,dict.Select(kv=>new item(){id = kv.Key,value=kv.Value}).ToArray() );
Deserialization:
var myDict = ((item[])serializer.Deserialize(stream)).ToDictionary(i =>i.id, i => i.value);
Accessing your dictionary values
foreach (KeyValuePair<int, string> pair in myDict )
{
if (pair.Key == any_integer_value_to_compare)
{
Console.WriteLine(pair.Value);
}
}
In this way you can systematically store the state of your dictionary values at the particular instance and access it later on by de-serializing the XML file.
To create or override a CSV file (note: there're no spaces and quotes)
977,String1
1021,String2
784,String3
801,String4
you can use Linq
File.WriteAllLines(#"C:\MyTest\MyFile.txt", dic
.Select(pair => String.Join(",", pair.Key, pair.Value)));
If you want to add quotations for values, add them (the simplest implementation)
File.WriteAllLines(#"C:\MyTest\MyFile.txt", dic
.Select(pair => String.Join(",", pair.Key, "\"" + pair.Value + "\"")));
you can't add spaces since line
{801, "String4"},
is totally equals to
{801,"String4"},
In case you want to convert the dictionary into String (and then combine it
with some other text(s) in order ro put into text file):
String text = String.Join(Environment.NewLine, dic
.Select(pair => String.Join(",", pair.Key, pair.Value))

How to convert the following JSON array into IDictionary<string, object>?

Following is the serialized JSON array I want to convert to IDictionary
[
{
"8475": 25532
},
{
"243": 521
},
{
"3778": 15891
},
{
"3733": 15713
}
]
When I tried to use
JsonConvert.DeserializeObject<IDictionary<string, object>>((string)jarray);
I got an error saying:
Cannot cast 'jarray' (which has an actual type of 'Newtonsoft.Json.Linq.JArray') to 'string'
The JSON deserializer requires only a string.
If you already have the JArray, all you have to do is convert it to a dictionary I guess.
Roughly something like this:
IDictionary<string,object> dict = jarray.ToDictionary(k=>((JObject)k).Properties().First().Name, v=> v.Values().First().Value<object>());
Check this for complete code with an example
I think there might be a better way to convert it to a dictionary though. I'll keep looking.
the JsonConvert.DeserializeObject<T> Method takes a JSON string, in other words a serialized object.
You have a deserialized object, so you'll have to serialize it first, which is actually pointless, considering you have all the information you need right there in the JArray object. If you are aiming just to get the objects from the array as key value pairs, you can do something like this:
Dictionary<string, object> myDictionary = new Dictionary<string, object>();
foreach (JObject content in jarray.Children<JObject>())
{
foreach (JProperty prop in content.Properties())
{
myDictionary.Add(prop.Name, prop.Value);
}
}
To turn your JArray into a string, you'll need to assign the key & values of the dictionary for each element. Mario gave a very accurate approach. But there's a somewhat prettier approach as long as you know how to convert each item into your desired type. The below example is for Dictionary<string, string> but can be applied to any Value type.
//Dictionary<string, string>
var dict = jArray.First() //First() is only necessary if embedded in a json object
.Cast<JProperty>()
.ToDictionary(item => item.Name,
item => item.Value.ToString()); //can be modified for your desired type

Flatten nested Dictionary<string, object>

I am deserializing some nested JSON with the following:
string json = #"{
""name"": ""charlie"",
""someID"": 123,
""level1"" : {
""name"": ""charlie 1"",
""someID"": 456
}
}";
JavaScriptSerializer serializer = new JavaScriptSerializer();
Dictionary<string, object> data = serializer.Deserialize<Dictionary<string, object>>(json);
Once this is done, the values of each dictionary key may be another Dictionary, and so on, multiple levels deep.
What I would like to do is to flatten the multi-level data so it's just a flat Array/List, with just all the JSON attribute names and their values. So that I end up with something like this:
name, "charlie"
someID, 123
name, charlie 1
someID, 456
I was heading down the path of using SelectMany() and so forth, but could not wrangle it to do what I am after.
I've been sort of waddling around with things like this:
var obj = data.Values.SelectMany<object, Dictionary<string, object>>(x => x);
But I am not able to satisfy the compiler. Yes, I am lost.
I am using .NET 3.5.
Func<Dictionary<string, object>, IEnumerable<KeyValuePair<string, object>>> flatten = null;
flatten = dict => dict.SelectMany(kv =>
kv.Value is Dictionary<string,object>
? flatten((Dictionary<string,object>)kv.Value)
: new List<KeyValuePair<string,object>>(){ kv}
);
var flatList = flatten(data).ToList();
You need recursion here:
IEnumerable<Tuple<string, string>> Flatten(this IDictionary dict)
{
foreach(DictionaryEntry kvp in dict)
{
var childDictionary = kvp.Value as IDictionary;
if(childDictionary != null)
{
foreach(var tuple in childDictionary.Flatten())
yield return tuple;
}
else
yield return Tuple.Create(kvp.Key.ToString(), kvp.Value.ToString());
}
}
// Usage:
var flatList = data.Flatten().ToList();
On .NET 3.5, you can use KeyValuePair<string, string> instead of Tuple<string, string>.
Please note that there is no KeyValuePair.Create, you need to use new KeyValuePair<string, string>(kvp.Key.ToString(), kvp.Value.ToString()) instead.

Categories

Resources