Search code examples
c#json.netjson-deserialization

C# Newtonsoft.Json DeserializeObject if json contains an invalid token


How can i deserialize this json in C# using Newtonsoft.Json.JsonConvert.DeserializeObject? The problem is that i cannot use "event" as a class property because its an invalid token.

{
  "resultsPage": {
    "results": {
      "event": {
        "location": {
          "city": "London, UK",
          "lng": -0.1150322,
          "lat": 51.4650846
        },
        "uri": "http://www.....",
        "displayName": "Test",
        "id": 3037536,
        "type": "Testtype",
        "start": {
          "time": "19:30:00",
          "date": "2010-02-16",
          "datetime": "2010-02-16T19:30:00+0000"
        },
        "status": "ok"
      }
    },
    "status": "ok"
  }
}

Solution

  • There's a few ways you could do this with Newtonsoft.

    JsonConvert.DeserializeObject will return an object of type JObject, this can be done either by not specifying a type (instead casting after deserializing) or by specifying the JObject type.

    From here you can access event because it is simply a key name, but you lose any strong typing of your json.

    var jobj = (JObject)Newtonsoft.Json.JsonConvert.DeserializeObject(json);    
    var _event = jobj["resultsPage"]["results"]["event"];
    

    Taking this a step further, you can use JsonConvert.DeserializeAnonymousType and specify the definition of your anonymous type, using @event or Event where event is present in the json. When accessing the property, you would need to use @event or Event depending on which you chose, and you gain the benefits of strongly typed objects.

    var jobj = Newtonsoft.Json.JsonConvert.DeserializeAnonymousType(json, new {
        resultsPage = new {
            results = new {
                @event = new {
                    location = new {
                        city = "",
                        lng = 0.0,
                        lat = 0.0
                    },
                    uri = "",
                    displayName = "",
                    id = 0,
                    type = "",
                    start = new {
                        time = "",
                        date = "",
                        datetime = new DateTime()
                    },
                    status = ""
                }
            },
            status = ""
        }
    });
    
    var _event = jobj.resultsPage.results.@event;
    

    Next, you could create classes take this anonymous object definition and split it out into classes, again using @event or Event and it will deserialize.

    var jobj = Newtonsoft.Json.JsonConvert.DeserializeObject<JsonClass>(json);
    var _event = jobj.resultsPage.results.@event;
    
    public class JsonClass
    {
        public ResultsPage resultsPage { get; set; }
        public string status { get; set; }
    }
    
    public class ResultsPage
    {
        public Results results { get; set; }
        public string status { get; set; }
    }
    
    public class Results
    {
        public Event @event { get; set; }
    }
    
    public class Event
    {
        public Location location { get; set; }
        ...
    }
    
    public class Location
    {
        public string city { get; set; }
    }
    

    Or you could look at using a property attribute to map a completely different property name to the json key (the below is a modified excerpt of the above).

    public class Results
    {
        [JsonProperty(PropertyName = "event")]
        public EventResult EventResult { get; set; }
    }
    
    public class EventResult
    {
        public Location location { get; set; }
    }