Nick
Nick

Reputation: 10499

How to deserialize custom json in C#

I am trying to deserialize a JSON file which elements are in the following format:

{"include\\fooo\\Gell.h": {
    "parents": [
        "include\\rfg\\ExplorableMa.h"
    ],
    "children": [
        "include\\rfg\\IEditable.h",
        "include\\rfg\\IExplorable.h",
        "Bar"
    ]
}}

There may be 1 or more elements following each other in the JSON file. I tried using the System.Runtime.Serialization.Json namespace, but I did not have much success with this code:

[DataContract]
class Vertex
{
    [DataMember] public string Path { get; set; }
}

using (Stream stream = File.OpenRead(@"file.json"))
{
    var serializer = new DataContractJsonSerializer(typeof(Vertex[]));
    Vertex[] verteces = (Vertex[])serializer.ReadObject(stream);
    // the array is not valid at this point
}

The code above is supposed to fill the array with a single vertex and its path equal to "include\\fooo\\Gell.h" in this specific case to start. What is the correct way to deserialize such a JSON file?

Upvotes: 1

Views: 1110

Answers (2)

dbc
dbc

Reputation: 116526

Firstly, note that your root JSON container is an object, not an array. The JSON standard specifies the following types of container:

  • The array which an ordered collection of values. An array begins with [ (left bracket) and ends with ] (right bracket). Values are separated by , (comma).

    Most JSON serializers map .Net enumerables to JSON arrays.

  • The object which is an unordered set of name/value pairs. An object begins with { (left brace) and ends with } (right brace).

    Most JSON serializers map dictionaries and non-enumerable, non-primitive types to JSON objects.

Thus you will need to deserialize to a different type, one which maps to an object with custom, variable property names that have values with fixed schema. Most serializers support to Dictionary<string, TValue> in such situations.

First define the following type:

public class VertexData
{
    public List<string> parents { get; set; }
    public List<string> children { get; set; }
}

Then, using you can deserialize to a Dictionary<string, VertexData> as follows as long as you are using .Net 4.5 or later as explained in this answer:

var serializer = new DataContractJsonSerializer(typeof(Dictionary<string, VertexData>)) { UseSimpleDictionaryFormat = true };
var vertices = (Dictionary<string, VertexData>)serializer.ReadObject(stream);
var paths = vertices.Keys.ToList();

If you would prefer to use you can deserialize to the same Dictionary<string, VertexData> as follows:

using (var reader = new StreamReader(stream))
using (var jsonReader = new JsonTextReader(reader))
{
    var vertices = JsonSerializer.CreateDefault().Deserialize<Dictionary<string, VertexData>>(jsonReader);
    var paths = vertices.Keys.ToList();
}

And finally with :

using (var reader = new StreamReader(stream))
{
    var jsonString = reader.ReadToEnd();

    var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
    var vertices = serializer.Deserialize<Dictionary<string, VertexData>>(jsonString);
    var paths = vertices.Keys.ToList();
}

Upvotes: 0

gliderkite
gliderkite

Reputation: 8928

Using Json.Net you could deserialize your file in this way (or similar):

using System.Collections.Generic;
using System.Windows;
using System.IO;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

class Vertex
{
    [JsonExtensionData]
    public IDictionary<string, JToken> _additionalData;
}

var content = File.ReadAllText(@"file.json");
var d = JsonConvert.DeserializeObject<Vertex>(content);

Have a look at these examples: http://james.newtonking.com/archive/2013/05/08/json-net-5-0-release-5-defaultsettings-and-extension-data

Upvotes: 2

Related Questions