Reputation: 419
I'm using Json.NET (http://james.newtonking.com/projects/json/help/) as a way to serialize and deserialize JSON from a server. Let's say I have the following JSON object:
{
"user" : {
"name" : "Bob",
"age" : 35
},
"location" : "California"
}
The only way that I can find to deserialize this in to native types is to use a custom DTO as follows:
string jsonString = ""; // json string from above
Response result = JsonConvert.DeserializeObject<Response> (jsonString);
where the Response class looks something like:
public class Response
{
[JsonProperty("user")]
public UserResponse User { get; set; }
[JsonProperty("location")]
public string Location { get; set; }
}
public class UserResponse
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("age")]
public int Age { get; set; }
}
I want to deserialize this in to native types but I'm in an environment where I don't always know what the JSON string will look like... so it's hard to use custom DTO's when I don't know exactly what I'm getting down the pipe. If I don't pass any class in to JsonConvert.DeserializeObject(), then I end up with Json.NET types instead of native types like strings, ints, etc. Any suggestions on how to get around this? Should I be using a different JSON library instead?
Thanks!
Upvotes: 2
Views: 1401
Reputation: 48114
This will not solve all of your problems (that's just not possible) but here is a solution that will allow you to parse json with limited information about what's coming back.
At the outer level you create an object call it Vehicle. This contains a Car, Boat, and Plane. You're requesting some Vehicle but you don't know whether it will be Car, Boat, or Plane (note this could easily be expanded to handle an array of Vehicles or many other more complex responses). In the schema you have some options like;
"id": "vehicle.schema.json",
"type": "object",
"required": true,
"additionalProperties": false,
"properties": {
"Car": {
"type": "object",
"required": false
//other properties
},
"Boat": {
"type": "object",
"required": false
//other properties
},
"Plane": {
"type": "object",
"required": false
//other properties
}
Above is the schema file you would add to your project. If you want to have several of these just add more Tuples to the _schemaTypes array below.
// code to set up your schema
// Associate types to their JsonSchemas. Order matters here.
// After each parse, the schema is added to resolver, which is used in subsequent parses.
_schemaTypes = new[]
{
Tuple.Create(typeof(Vehicle), "vehicle.schema.json"),
}
.ToDictionary(
x => x.Item1,
x => JsonSchema.Parse(
File.ReadAllText(
Path.Combine(AppDomain.CurrentDomain.RelativeSearchPath ?? "", @"Serialization\Schemas\") + x.Item2),
resolver));
//method to return your deserialized object
public T Deserialize<T>(IRestResponse response)
{
var schema = _schemaTypes[typeof(T)];
T result = _serializer.Deserialize<T>(
new JsonValidatingReader(
new JsonTextReader(
new StringReader(response.Content)))
{
Schema = schema
});
return result;
}
Now after you parse your response you will have a more general object and from there you can write some code to figure out what the more specific object returned was. I'm using this type of approach to parse json where it has several levels of nested objects and arrays of objects and it is rather effective.
Upvotes: 1