I need to convert to dictionary JSON array of objects with key "id" and value "score" properties like the following
[{"score":0.6990418,"id":"4833909335"},
{"score":0.8079009,"id":"4833874639"},
{"score":0.8079009,"id":"4834247506"}].
Dictionary keys should have values of "id" property, and dictionary values shoud be copied from "score".
Note that it is not a deserialization, but transforming/mapping when some information not copied to target object(e.g. names of properties and potentially other properties)
I found similar question How to deserialize the json array of objects to dictionary , that was incorrectly closed as duplicate of different question about deserializing different JSON object with multiple properties.
I've tried to reopen it, but without success.
I've created extension methods to allow extract pair of properties from elements of JSON array
public static Dictionary< string, string> JsonArrayToDictionary( string strJson, string keyName,string valueName)
{
var array = JArray.Parse(strJson) ;
var dictionary = JsonArrayToDictionary(array, keyName, valueName);
return dictionary;
}
public static Dictionary<string , string > JsonArrayToDictionary(this JArray array, string keyName, string valueName)
{
if (array != null)
{
var dict = array.ToDictionary(x => x[keyName].ToString(), x => x[valueName].ToString());
return dict;
}
return null;
}
[TestClass()]
public class JsonHelperExtensionsTests
{
[ TestMethod()]
public void JsonArrayToDictionaryTest()
{
var jsonArray= #"[{""score "":0.6990418,"" id"": ""ID1"" },{""score "":0.8079009,"" id"": ""ID2"" }]";
var dict= JsonHelperExtensions.JsonArrayToDictionary(jsonArray, "id" , "score");
dict.Count.Should().Be(2);
dict[ "ID1"].Should().Be("0.6990418" );
}
}
Current solution for current time:
var jsArray = JObject.Parse(response);
var arrayDictionary = JsonConvert.DeserializeObject<Dictionary<string, dynamic>[]>(jsArray.ToString());
Related
I have a Python code that sends this JSON through MQTT.
message = {
"name":"Alex",
"date": 2021,
"activity":["act1","act2","act3"],
}
Then I receive and Deserialize it in a C# script
public void Client_MqttMsgPublishReceived(object sender, MqttMsgPublishEventArgs e)
{
var Message = System.Text.Encoding.Default.GetString(e.Message);
Dictionary<string, string> MessageDICT = JsonConvert.DeserializeObject<Dictionary<string, string>>(Message);
}
The keys "name" and "date" has no problem being deserialized into the dictionary. However the error comes with "activity" due it being an array. Where it states "Unexpected character encountered while parsing value:[". I have seen methods where they deserialize it separately (where the array is sent in a different message), however this is not what I want. Is there a way I can deserialize the message as a whole?
Thanks.
You have your dictionary declared as <string, string>, but "activity" is an array. So this is why it does not work.
If you want to keep using a dictionary, then you can instead declare it as <string, object> and then it will work for any type of data. But you will need to then check what Type it is before you later try to use it.
Dictionary<string, object> MessageDICT = JsonConvert.DeserializeObject<Dictionary<string, object>>(message);
You can then access it like this:
object first = ((JArray)MessageDICT["activity"])[0];
But if possible, you should try to use a fixed class for the data and deserialize that.
Otherwise, maybe a dynamic is better.
Hi why not use a class to read the json
public class Message
{
public string name {get;set;}
public string date {get;set;} //actually, this looks like an int the json, however...
public string[] activity {get;set;}
}
usage
var res = JsonConvert.DeserializeObject<Message>(message);
Using the Mongo .Net Driver 2.7.2, I am attempting to customize how a Dictionary property is getting serialized. Specifically, I would like the Dictionary's value, a List<string> to serialize as a simple array.
Current document structure generated by serializer
This is how the property is currently serializing. As you can see, somePropertyis being serialized as an object, with _t and _v storing the .NET type and value.
viewedBy: Object
someProperty: Object
_t: "System.Collections.Generic.List`1[System.String]"
_v: Array
I understand the type information is stored for deserialization back into the c# POCO, but for my case I don't need this metadata, as my type is just a string array.
Desired document structure
I would like the property values to serialize as simple arrays of strings,as below
viewedBy: Object
someProperty: Array
Here is the class I am attempting to customize the serialization strategy for.
public class MyDocument
{
public Dictionary<string, List<string>> ViewedBy { get; set; }
}
Current Mapping
Here is the mapping information I have provided for my class.
BsonClassMap.RegisterClassMap<MyDocument>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.ViewedBy)
.SetElementName("viewedBy")
.SetSerializer(new
DictionaryInterfaceImplementerSerializer<Dictionary<string,
List<string>>>(DictionaryRepresentation.Document));
// How do I specify the dictionary value should serialize as simple array?
});
Question
How can I instruct the serializer to serialize the dictionary's value, of .NET type List<string> to serialize into a simple string array?
Preference is for a fluent mapping solution, rather than using Attributes.
Include System.Linq
use this the way you want.
Dictionary<string, List<string>> m = new Dictionary<string, List<string>>();
m.Add("1", new List<string> { "Sumit", "Raj" });
m.Add("2", new List<string> { "Rahul", "Raj" });
/*Array of string. Currently 4 values*/
var res = m.SelectMany(x => x.Value).ToArray();
/*Array of List<string>. Currently 2 List With 2 Values*/
var res1 = m.Select(x => x.Value).ToArray();
I am trying to get value of label from following string.
I have a string in this format.
var string = "[{\"key\":\"182\",\"label\":\"testinstitution\"}]"
dynamic dict = new JavaScriptSerializer().Deserialize<dynamic>(string);
string inst = dict["label"]; //This is not working
I am getting dict in form of key value pair object but I am not able to get value of label. I cannot use JSON.NET.
To retrieve value of label from your string use string inst = dict[0]["label"];.
Explanation
The reason why you need additional [0] is because deserialization returns array of key value pairs. First object from that array will go to index [0], second object from array to index [1] an so on. Your string has array of only one object. Here is an example of when you have two objects, where second object has another object inside of it, in which case you would have to write dict[1]["foo"]["two"] to get to desired value:
var myString = #"
[
{
'one': '1'
},
{
'foo':
{
'two': '2'
}
}
]";
dynamic dict = new JavaScriptSerializer().Deserialize<dynamic>(myString);
string inst = dict[1]["foo"]["two"];
Additional FYI
If you know structure of your data consider using strong types (as suggested in one of the comments). Here is example of how you would do it:
public class Data
{
public string key { get; set; }
public string label { get; set; }
}
class Program
{
static void Main(string[] args)
{
var myString = #"
[{
'key': 182,
'label': 'testinstitution'
}]";
List<Data> dict = new JavaScriptSerializer().Deserialize<List<Data>>(myString);
foreach (var d in dict)
Console.WriteLine(d.key + " " + d.label);
Console.ReadKey();
}
}
Note that properties key and value in your Data object much match names of those in your array of objects exactly.
I have a data model that is defined as a class in C#. I need to merge two objects using JObject.Merge, but in the case of one particular property I need to ignore empty string values from the 2nd object, similar to how you would ignore null values. Is there an existing attribute property for this, or do I somehow need to write my own?
void Main()
{
string json1 = #"{ Foo: ""foo1"", Bar: ""bar1"" }";
string json2 = #"{ Foo: ""foo2"", Bar: null }";
string json3 = #"{ Foo: ""foo3"", Bar: """" }";
var model1 = JObject.Parse(json1);
var model2 = JObject.Parse(json2);
model1.Merge(model2);
model1.Dump();
model1 = JObject.Parse(json1);
model2 = JObject.Parse(json3);
model1.Merge(model2);
model1.Dump();
}
public class Model
{
[JsonProperty("foo")]
public string Foo { get ; set; }
[JsonProperty("bar", NullValueHandling = NullValueHandling.Ignore)]
public string Bar { get ; set; }
}
Output (1): Model.Bar = "bar1"
Output (2): Model.Bar = "";
Desired output of (2): Model.Bar = "bar1"
EDIT: OK, I realized that attributes could not be applied since I needed to work with the raw json string only as input. This was mainly due to the fact that my classes had attributes with default values. Merging classes with empty values would trigger the defaults and end up overwriting the original, which is what I didn't want. I need to be able to take a partial json representation of a class and update the original. Sorry if that wasn't clear from the get-go. I'll update what I ended up doing an answer.
You could remove the properties with empty string values from the JObject you want to merge in, using the following extension methods:
public static class JsonExtensions
{
public static void RemovePropertiesByValue(this JToken root, Predicate<JValue> filter)
{
var nulls = root.DescendantsAndSelf().OfType<JValue>().Where(v => v.Parent is JProperty && filter(v)).ToList();
foreach (var value in nulls)
{
var parent = (JProperty)value.Parent;
parent.Remove();
}
}
public static IEnumerable<JToken> DescendantsAndSelf(this JToken node)
{
if (node == null)
return Enumerable.Empty<JToken>();
var container = node as JContainer;
if (container != null)
return container.DescendantsAndSelf();
else
return new [] { node };
}
}
Then use it like:
model2.RemovePropertiesByValue(v => v.Type == JTokenType.String && string.IsNullOrEmpty((string)v.Value));
Note this doesn't remove empty strings from arrays because that would mess up array indexing, and therefore merging. Do you need that also?
I manipulated the JObject dictionary keys to massage the specific entry. I feel dirty, but it works. I can't think of a "good" way to do this.
model1 = JObject.Parse(json1);
model2 = JObject.Parse(json3);
IDictionary<string, JToken> dictionary = model2;
dictionary["Bar"] = string.IsNullOrEmpty((string)dictionary["Bar"])
? null
: dictionary["Bar"];
model1.Merge(model2);
Is there a way to convert a Json Object to a Multidimensional C# Array? I know it might be impractical but I can't be bothered to write classes and then deserialize the strings into them.
List<string> ohyeah = (List<string>)JsonConvert.DeserializeObject(g.CommToken);
That returns an Invalid Cast exception!
Example:
{"method":"getCommunicationToken","header":{"uuid":"9B39AAB0-49A6-AC7A-BA74-DE9DA66C62B7","clientRevision":"20100323.02","session":"c0d3e8b5d661f74c68ad72af17aeb5a1","client":"gslite"},"parameters":{"secretKey":"d9b687fa10c927f102cde9c085f9377f"}}
I need to get something like that :
j["method"]; //This will equal to getCommunicationToken
j["header"]["uuid"]; //This will equal to 9B39AAB0-49A6-AC7A-BA74-DE9DA66C62B7
I literally need to parse the json object into an array.
The Parse and SelectToken methods of the JObject class do exactly what you want/need.
The Library can be found here: http://json.codeplex.com/releases/view/37810
JObject o = JObject.Parse(#"
{
""method"":""getCommunicationToken"",
""header"":
{
""uuid"":""9B39AAB0-49A6-AC7A-BA74DE9DA66C62B7"",
""clientRevision"":""20100323.02"",
""session"":""c0d3e8b5d661f74c68ad72af17aeb5a1"",
""client"":""gslite""
},
""parameters"":
{
""secretKey"":""d9b687fa10c927f102cde9c085f9377f""
}
}");
string method = (string)o.SelectToken("method");
// contains now 'getCommunicationToken'
string uuid = (string)o.SelectToken("header.uuid");
// contains now '9B39AAB0-49A6-AC7A-BA74DE9DA66C62B7'
By the way: This is not a multidimensional array:
j["header"]["uuid"];
You would have those indexers for example in a dictionary with dictionaries as values, like:
Dictionary<string, Dictionary<string, string>> j;
But here you would just have a "depth" of two indexes. If you want a datastructure with indexers in this "jagged array style", you would write a class like:
class JaggedDictionary{
private Dictionary<string, string> leafs =
new Dictionary<string, string>();
private Dictionary<string, JaggedDictionary> nodes =
new Dictionary<string, JaggedDictionary>();
public object this[string str]
{
get
{
return nodes.Contains(str) ? nodes[str] :
leafs.Contains(str) ? leafs[str] : null;
}
set
{
// if value is an instance of JaggedDictionary put it in 'nodes',
// if it is a string put it in 'leafs'...
}
}
}