Reputation: 10499
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
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 datacontractjsonserializer 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 json.net 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 javascriptserializer:
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
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