Generic JSON parser in .NET / WPF? - c#

I've read lots of tutorials on how to deserialize a JSON object to an object of a particular using DataContractJsonSerializer. However, I'd like to deserialize my object to a Dictionary consisting of either Strings, Arrays or Dictionaries, such as System.Json does with SilverLight when I say JsonObject.Parse(myJSONstring).
Is there an equivalent to System.Json that I can use in my WPF project?
(just a short background: I'm fetching JSON objects that have way to much info, and I just want to use a little bit to fill out a String array)
Cheers
Nik

Just use .NET's built-in JavaScriptSerializer.
var jss = new JavaScriptSerializer();
var data = jss.Deserialize<dynamic>(jsonString);
//"data" actually implements IDictionary<string, object>
var p1 = data["Property1"];
var p2 = data["Property2"];
Don't forget to reference "System.Web.Extensions"

Take a look at the C# section (scoll to the bottom) of http://json.org/, they have several implementations of serializers and parsers that should help.

I successfully use JayRock: http://jayrock.berlios.de/
public class JayRockMarshaller : IMarshaller
{
public ICollection Read(string text)
{
return (ICollection)new ImportContext().Import(new JsonTextReader(new StringReader(text)));
}
public string Write(ICollection objectToMarshal)
{
var writer = new StringWriter();
new ExportContext().Export(objectToMarshal, new JsonTextWriter(writer));
return writer.ToString();
}
}
Works for both Dictionaries and Lists like a dream.

Also look at https://github.com/jlarsson/Kiwi.Json it handles all sorts of datatypes and you can easily create your own converter if the built in doesn't fit.
There's blog where you can find samples on this for example: http://dancewithcode.wordpress.com/2012/03/24/case-study-custom-json-converter-for-datatable/

Related

Get Tuple from string returned by Tuple.ToString()

Say, we have that code:
var tuple = new Tuple<double, int>(10.6, 2);
var tupleString = tuple.ToString(); //returns "(10.6, 2)";
Can we get a new Tuple instance from tupleString without implementing any custom parsers and JsonConverters and extending TypeConverter?
UPDATE 1
In my production code I have SortedList<Tuple<DayOfWeek, double>, double>. That list is serialized by Json.NET,that converts Dictionary keys by .ToString(). Then JSON is sent to frontend application. Then frontend application send request with that serialized key to server. I have to convert that key to .NET Tuple, but I don't know how to do that.
Of course you can. You can 'simply' parse the output string, but I hope you like writing parsing algorithms then which might get hard, especially when it involves strings and objects...
See for example this one, which is impossible to parse:
var tuple = new Tuple<string, int>("10, 6", 2);
var tupleString = tuple.ToString(); //returns "(10, 6, 2)";
I would suggest to use the items in the tuple itself instead of making a string out of it first:
Tuple<int> tuple2 = tuple.Item2;
If you are serializing it using JSON.NET, you should write or use a custom serializer, like the one mentioned here.
I solved my problem by another way using this answer of Nate Barbettini.
I changed his code to that:
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
Type type = value.GetType();
IEnumerable keys = (IEnumerable)type.GetProperty("Keys").GetValue(value, null);
IEnumerable values = (IEnumerable)type.GetProperty("Values").GetValue(value, null);
IEnumerator valueEnumerator = values.GetEnumerator();
writer.WriteStartObject();
foreach (object key in keys)
{
valueEnumerator.MoveNext();
writer.WritePropertyName(JsonConvert.SerializeObject(key));
serializer.Serialize(writer, valueEnumerator.Current);
}
writer.WriteEndObject();
}
Then just set custom JsonConverterAttribute to required IDictionary<,> and Json.NET will serialize its keys by JsonConvert.SerializeObject() instead of .ToString(). So that Tuple can be deserialized by Json.NET correctly.

DataContractJsonSerializer dynamic object deserialization

I would like to go with DataContractJsonSerializer instead of any third party libs like Json.NET I need to deserialize Json stream which can be one of my C# classes, and I dont know which one it is what i want to do is Deserialize json data -> determine type of this object -> do something with deserialized object according to type of this object. Is there anything to do with DataContractJsonSerializer.KnownTypes Property? Im really new to json.
what i want to do is Deserialize json data -> determine type of this object -> do something with deserialized object according to type of this object. Is there anything to do with DataContractJsonSerializer.KnownTypes Property?
Yes, it is related to the known types. Firstly, you need to specify the type you want to de-serialize in the constructor function. Then you can specify the types may be present in may be present in the object graph.
DataContractJsonSerializer Constructor (Type, IEnumerable)
But I still recommend you using the JSON.NET which will be easier than DataContractJsonSerializer, and the performance is even better. In ASP.NET Web API, JSON.NET is the default JSON serializer.
or JavaScriptSerializer
var jss = new JavaScriptSerializer();
var dict = jss.Deserialize<Dictionary<string, dynamic>>(strRet);
StringBuilder sbErr = new StringBuilder(string.Format("{0} ({1}): {2}", rep.StatusDescription, dict["code"], Environment.NewLine));
if ((dict["errors"] is Dictionary<string, dynamic>)) {
foreach (KeyValuePair<string, dynamic> item in dict["errors"]) {
sbErr.AppendFormat("{0}=", item.Key);
foreach (string item2 in item.Value)
sbErr.AppendFormat("{0}. ", item2);
}
}

How do you parse a JSON.NET file without a defined structure?

I'm using an API from OpenCalais that gives me a json string that contains a bunch of JSON objects. The problem is that depending on what I pass into the API the structure of the JSON string changes, which means that I can't cast the deseralization against a custom class I could make. Another problem is that the output isn't in key value form, but rather a complicated object structure. Here is an example of the output-
{"doc":
{"info":
{"allowDistribution":"true",
"allowSearch":"true",
"calaisRequestID":"c1cdd79a-ed89-8431-138c-50e8a37100f9",
"externalID":"17cabs901",
"id":"http://id.opencalais.com/0RCcU306*HTR05*7HlUb5A",
"docId":"http://d.opencalais.com/dochash-1/6188237f-a2a5-3263-95b7-ea894ba98298",
"document":"Bill Gates worked at Microsoft from 2008 to 2011. He is also married to Melinda Gates.",
"docTitle":"",
"docDate":"2012-07-26 15:51:00.885",
"externalMetadata":"",
"submitter":"ABC"}
So you can see there are multiples levels of objects here and there is no key value structure. What I need from this code is essentially all of the name/value info in a dictionary. Then I can sort through based on the keys to the relevant info. It would also be cool if I could somehow also grab the parent of the object value. So for example the output I want is key: allowSearch, value: true, parent: info. I have been trying to mess around with different method of deserialization, dynamic objects, and just plain parsing using functions like .Ancestor and I haven't found anything useful. Any help would be greatly appreciated.
Have you looked at JSON.NET? It can dynamically parse JSON which you can then iterate through:
using Newtonsoft.Json.Linq;
JObject rootObject = JObject.Parse(jsonString);
You can iterate through the children, or search for other nodes like this:
JToken info = rootObject.SelectToken("info");
Json.NET support LINQ to JSON under the Newtonsoft.Json.Linq namespace.
The example to use JObject
JObject o = JObject.Parse(#"{'CPU': 'Intel','Drives': ['DVD read/writer','500 gigabyte hard drive']}");
string cpu = (string)o["CPU"];
// Intel
string firstDrive = (string)o["Drives"][0];
// DVD read/writer
IList<string> allDrives = o["Drives"].Select(t => (string)t).ToList();
// DVD read/writer
// 500 gigabyte hard drive
You can use DeserializeObject which essentially returns a Dictionary<string, object>.
For example:
JavaScriptSerializer serializer = new JavaScriptSerializer();
Dictionary<string, object> myGraph = (Dictionary<string, object>)serializer.DeserializeObject(myJson);
To read stuff from the myGraph dictionary, you will have to cast each step of the way.
For example:
Dictionary<string, object> doc = (Dictionary<string, object>)myGraph["doc"];
Dictionary<string, object> info = (Dictionary<string, object>)doc["info"];
string externalID = (string)info["externalID"];
I'm sure you could genericize it a bit, but I think that should work with the json you posted.

javascript to C# code Array implementation

this is javascript code, I want to change it into C# code, same as this is, b/c again I'll change it to javascript object
data: [['2-2010',45.0],['IE', 26.8],[ 'Chrome',12.8],['Safari',8.5],['Opera',6.2],['Others', 0.7]]
actually I'm writing a wrapper which will take values in C# language and then through json serialize I'll convert the code into json.
I can't do it like this, b/c at the time of creating json it would be some thing like
C#
class dataArray
{
public string browserId;
public double percentRate;
}
JS Generated by the above class but not useable for me b/c of the variable browser and percentRate
dataArray = {browser: 'chrome', 'percentRate':30.3}
I was expecting something like this List<string,double> but it would never work :D
You need a List of object arrays to get the output that you're looking for. I used JSON.net for the example code below.
class Program
{
static void Main(string[] args)
{
List<object[]> kvp = new List<object[]>()
{
new object[] {"2-2010", 45},
new object[] {"IE", 26.8},
new object[] {"Chrome", 12.8},
new object[] {"Safari", 8.5}
};
var json = JsonConvert.SerializeObject(kvp);
Console.WriteLine(json);
//deserialize it to a List<object[]>
var json2 = "[[\"2-2010\",45.0],[\"IE\", 26.8],[\"Chrome\",12.8],[\"Safari\",8.5]]";
var kvp2 = JsonConvert.DeserializeObject<List<object[]>>(json2);
}
}
No, you'd better have an array of dictionaries, each dictionary will be equal to the object and its key and values will be his property and value
You could use anonymous types which looks a lot like the JS code, but without single quoutes around percentRate. You could also use Tuples, which is Tuple<string, float> and is basically a pair of values. Multidimensional or jagged arrays are another option.

In C#, How can I serialize Queue<>? (.Net 2.0)

At the XmlSerializer constructor line the below causes an InvalidOperationException which also complains about not having a default accesor implemented for the generic type.
Queue<MyData> myDataQueue = new Queue<MyData>();
// Populate the queue here
XmlSerializer mySerializer =
new XmlSerializer(myDataQueue.GetType());
StreamWriter myWriter = new StreamWriter("myData.xml");
mySerializer.Serialize(myWriter, myDataQueue);
myWriter.Close();
It would be easier (and more appropriate IMO) to serialize the data from the queue - perhaps in a flat array or List<T>. Since Queue<T> implements IEnumerable<T>, you should be able to use:
List<T> list = new List<T>(queue);
Not all parts of the framework are designed for XML serialization. You'll find that dictionaries also are lacking in the serialization department.
A queue is pretty trivial to implement. You can easily create your own that also implements IList so that it will be serializable.
if you want to use the built in serialization you need to play by its rules, which means default ctor, and public get/set properties for the members you want to serialize (and presumably deserialize )
on the data type you want to serialize (MyData)
In my case i had a dynamic queue and i had to save and load the state of this one.
Using Newtonsoft.Json:
List<dynamic> sampleListOfRecords = new List<dynamic>();
Queue<dynamic> recordQueue = new Queue<dynamic>();
//I add data to queue from a sample list
foreach(dynamic r in sampleListOfRecords)
{
recordQueue.Enqueue(r);
}
//Serialize
File.WriteAllText("queue.json",
JsonConvert.SerializeObject(recordQueue.ToList(), Formatting.Indented));
//Deserialize
List<dynamic> data =
JsonConvert.DeserializeObject<List<dynamic>>(File.ReadAllText("queue.json"));

Categories

Resources