28

I know that I can use JsonConvert.DeserializeObject<T>(string), however, I need to peek into the object's _type (which may not be the first parameter) in order to determine the specific class to cast to. Essentially, what I am wanting to do is something like:

//Generic JSON processor for an API Client.
function MyBaseType ProcessJson(string jsonText)
{
  var obj = JObject.Parse(jsonText);
  switch (obj.Property("_type").Value.ToString()) {
    case "sometype":
      return obj.RootValue<MyConcreteType>();
      //NOTE: this doesn't work... 
      // return obj.Root.Value<MyConcreteType>();
    ...
  }
}
...

// my usage...
var obj = ProcessJson(jsonText);
var instance = obj as MyConcreteType;
if (instance == null) throw new MyBaseError(obj);
lorond
  • 3,856
  • 2
  • 37
  • 52
Tracker1
  • 19,103
  • 12
  • 80
  • 106
  • I should point out that mainly I am wanting to avoid parsing the JSON twice if I can. – Tracker1 Apr 18 '12 at 22:11
  • What kinf of JSON are you using that has type information? JSON is a notation of property-value pairs (where the value can be an array or another type including its own pairs of property-value). But I've never seen a JSON with type information. When you "stringify" and object to JSON all type info is lost! – JotaBe Apr 19 '12 at 00:30
  • @JotaBe it's part of an exposed restful API that I'm building a client for, to use in a project I'm working on. It's typically a good idea, when you expose an API via JSON to have all responses wrapped in an object, so the outermost response is always an object (even for error responses), and to have some sort of Type information with that object... It's really helpful in terms of processing errors vs. expected responses at the client level... – Tracker1 Apr 21 '12 at 21:05
  • (Comment from deleted answer) - In my case, the API is from another system, written in Python. The "_type" in question will be "error" or one of a few defined types, such as "report_summary" or "order". – Tracker1 Jul 09 '18 at 20:22

2 Answers2

49

First parse the JSON into a JObject. Then lookup the _type attribute using LINQ to JSON. Then switch depending on the value and cast using ToObject<T>:

var o = JObject.Parse(text);
var jsonType = (String)o["_type"];

switch(jsonType) {
    case "something": return o.ToObject<Type>();
    ...
}
yamen
  • 15,390
  • 3
  • 42
  • 52
0

JSON.NET has no direct ability to support both requisites:

  • custom name of the property holding the type name
  • look for the property anywhere in the object

The first requisites is fulfilled by JsonSubTypes The second one by specifying thh right MetadataPropertyHandling

JotaBe
  • 38,030
  • 8
  • 98
  • 117