If you don't know the exact data contract (or you don't care about it), then you can easily do that with the help of System.Web.Helpers.Json
class and a dynamic
object:
dynamic json = System.Web.Helpers.Json.Decode(@"{ ""Name"": ""Jon Smith"", ""Address"": { ""City"": ""New York"", ""State"": ""NY"" }, ""Age"": 42 }");
Console.WriteLine(json.Name); // prints "Jon Smith"
Console.WriteLine(json.Address.State); // prints "NY"
A note on that: you will have to add reference to the System.Web.Helpers
assembly.
Of course not everyone likes dynamic
, there are some people who prefer to have well defined data contracts. For them the solution is a little bit longer:
You have to create matching classes for your data contracts, and attribute them accordingly:
// class for the root object:
[DataContract]
public class Person
{
[DataMember]
public string Name { get; set; }
[DataMember]
public Address Address { get; set; }
[DataMember]
public int Age { get; set; }
}
// class for the address object:
[DataContract]
public class Address
{
[DataMember]
public string City { get; set; }
[DataMember]
public string State { get; set; }
}
You can mark members with IgnoreDataMember
attribute to, well, ignore them, or add IsRequired=true
to make them mandatory.
After defining those contracts, you can easily parse the JSON string into a Person
object:
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Person));
using( MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(@"{ ""Name"": ""Jon Smith"", ""Address"": { ""City"": ""New York"", ""State"": ""NY"" }, ""Age"": 42 }")))
{
var person = (Person)ser.ReadObject(stream);
Console.WriteLine(person.Name); // prints "Jon Smith"
Console.WriteLine(person.Address.State); // prints "NY"
}
Note: the DataContractJsonSerializer
resides in the System.ServiceModel.Web
assembly, so you will have to add a reference for that. (And of course for the System.Runtime.Serialization
assembly as well.)
To make it easier to use, you can add static Parse
and TryParse
methods to your data contract class:
public static Person Parse(string jsonString)
{
if (String.IsNullOrWhiteSpace(jsonString)) throw new ArgumentNullException("The jsonString parameter shouldn't be null or an empty string.");
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Person));
using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(jsonString)))
{
return (Person)ser.ReadObject(stream);
}
}
public static bool TryParse(string jsonString, out Person result)
{
try
{
result = Person.Parse(jsonString);
return true;
}
catch (Exception ex)
{
if (ex is ArgumentNullException || ex is SerializationException)
{
result = null;
return false;
}
throw;
}
}
As L.B. mentioned in their comment, you can use JavaScriptSerializer
- if you add a reference to the System.Web.Extensions
assembly - to make it even simpler:
var person = new JavaScriptSerializer().Deserialize<Person>(@"{ ""Name"": ""Jon Smith"", ""Address"": { ""City"": ""New York"", ""State"": ""NY"" }, ""Age"": 42 }");
For that you still need the classes from above, but you can leave out the - "ugly" - attributes if you would like to. (But with this method you lose the ability to mark parts as mandatory...)