I have the following code:
var user = (Dictionary<string, object>)serializer.DeserializeObject(responsecontent);
The input in responsecontent is JSON, but it is not properly deserialized into an object. How should I properly deserialize it?
I am assuming you are not using Json.NET (Newtonsoft.Json NuGet package). If this the case, then you should try it.
It has the following features:
LINQ to JSON
The JsonSerializer for quickly converting your .NET objects to JSON and back again
Json.NET can optionally produce well formatted, indented JSON for debugging or display
Attributes like JsonIgnore and JsonProperty can be added to a class to customize how a class is serialized
Ability to convert JSON to and from XML
Supports multiple platforms: .NET, Silverlight and the Compact Framework
Look at the example below. In this example, JsonConvert class is used to convert an object to and from JSON. It has two static methods for this purpose. They are SerializeObject(Object obj) and DeserializeObject<T>(String json):
using Newtonsoft.Json;
Product product = new Product();
product.Name = "Apple";
product.Expiry = new DateTime(2008, 12, 28);
product.Price = 3.99M;
product.Sizes = new string[] { "Small", "Medium", "Large" };
string json = JsonConvert.SerializeObject(product);
//{
// "Name": "Apple",
// "Expiry": "2008-12-28T00:00:00",
// "Price": 3.99,
// "Sizes": [
// "Small",
// "Medium",
// "Large"
// ]
//}
Product deserializedProduct = JsonConvert.DeserializeObject<Product>(json);
As was answered here - Deserialize JSON into C# dynamic object?
It's pretty simple using Json.NET:
dynamic stuff = JsonConvert.DeserializeObject("{ 'Name': 'Jon Smith', 'Address': { 'City': 'New York', 'State': 'NY' }, 'Age': 42 }");
string name = stuff.Name;
string address = stuff.Address.City;
Or using Newtonsoft.Json.Linq :
dynamic stuff = JObject.Parse("{ 'Name': 'Jon Smith', 'Address': { 'City': 'New York', 'State': 'NY' }, 'Age': 42 }");
string name = stuff.Name;
string address = stuff.Address.City;
Here are some options without using third party libraries:
// For that you will need to add reference to System.Runtime.Serialization
var jsonReader = JsonReaderWriterFactory.CreateJsonReader(Encoding.UTF8.GetBytes(#"{ ""Name"": ""Jon Smith"", ""Address"": { ""City"": ""New York"", ""State"": ""NY"" }, ""Age"": 42 }"), new System.Xml.XmlDictionaryReaderQuotas());
// For that you will need to add reference to System.Xml and System.Xml.Linq
var root = XElement.Load(jsonReader);
Console.WriteLine(root.XPathSelectElement("//Name").Value);
Console.WriteLine(root.XPathSelectElement("//Address/State").Value);
// For that you will need to add reference to System.Web.Helpers
dynamic json = System.Web.Helpers.Json.Decode(#"{ ""Name"": ""Jon Smith"", ""Address"": { ""City"": ""New York"", ""State"": ""NY"" }, ""Age"": 42 }");
Console.WriteLine(json.Name);
Console.WriteLine(json.Address.State);
See the link for more information about System.Web.Helpers.Json.
Update: Nowadays the easiest way to get the Web.Helpers is to use the NuGet package.
If you don't care about earlier windows versions you can use the classes of the Windows.Data.Json namespace:
// minimum supported version: Win 8
JsonObject root = Windows.Data.Json.JsonValue.Parse(jsonString).GetObject();
Console.WriteLine(root["Name"].GetString());
Console.WriteLine(root["Address"].GetObject()["State"].GetString());
If .NET 4 is available to you, check out: http://visitmix.com/writings/the-rise-of-json (archive.org)
Here is a snippet from that site:
WebClient webClient = new WebClient();
dynamic result = JsonValue.Parse(webClient.DownloadString("https://api.foursquare.com/v2/users/self?oauth_token=XXXXXXX"));
Console.WriteLine(result.response.user.firstName);
That last Console.WriteLine is pretty sweet...
Another native solution to this, which doesn't require any 3rd party libraries but a reference to System.Web.Extensions is the JavaScriptSerializer. This is not a new but a very unknown built-in features there since 3.5.
using System.Web.Script.Serialization;
..
JavaScriptSerializer serializer = new JavaScriptSerializer();
objectString = serializer.Serialize(new MyObject());
and back
MyObject o = serializer.Deserialize<MyObject>(objectString)
System.Text.Json
.NET core 3.0 comes with System.Text.Json built-in which means you can deserialize/serialize JSON without using a third-party library.
Serialize/Deserialize
To serialize your class(es) to JSON string:
var json = JsonSerializer.Serialize(model);
To deserialize the JSON into a strongly typed class:
var model = JsonSerializer.Deserialize<Model>(json);
Parse (.NET 6)
.NET 6 introduced the System.Text.Json.Nodes namespace which enables DOM parsing, navigation and manipulation in a similar manner to Newtonsoft.Json using the new classes JsonObject, JsonArray, JsonValue, and JsonNode.
// JsonObject parse DOM
var jsonObject = JsonNode.Parse(jsonString).AsObject();
// read data from DOM
string name = jsonObject["Name"].ToString();
DateTime date = (DateTime)jsonObject["Date"];
var people = jsonObject["People"].Deserialize<List<Person>>();
Similar methods apply to JsonArray. This answer provides more details on JsonObject.
One thing to note is that System.Text.Json does not automatically handle camelCase JSON properties when using your own code (however, it does when using MVC/WebAPI requests and the model binder).
To resolve this you need to pass JsonSerializerOptions as a parameter.
JsonSerializerOptions options = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase, // set camelCase
WriteIndented = true // write pretty json
};
// pass options to serializer
var json = JsonSerializer.Serialize(order, options);
// pass options to deserializer
var order = JsonSerializer.Deserialize<Order>(json, options);
System.Text.Json is also available for .Net Framework and .Net Standard as a Nu-get package System.Text.Json
Edit
In .NET 6 JsonNode.Parse() provides the functionality to parse "unknown" json
You could also have a look at the DataContractJsonSerializer
System.Json works now...
Install nuget https://www.nuget.org/packages/System.Json
PM> Install-Package System.Json -Version 4.5.0
Sample:
// PM>Install-Package System.Json -Version 4.5.0
using System;
using System.Json;
namespace NetCoreTestConsoleApp
{
class Program
{
static void Main(string[] args)
{
// Note that JSON keys are case sensitive, a is not same as A.
// JSON Sample
string jsonString = "{\"a\": 1,\"b\": \"string value\",\"c\":[{\"Value\": 1}, {\"Value\": 2,\"SubObject\":[{\"SubValue\":3}]}]}";
// You can use the following line in a beautifier/JSON formatted for better view
// {"a": 1,"b": "string value","c":[{"Value": 1}, {"Value": 2,"SubObject":[{"SubValue":3}]}]}
/* Formatted jsonString for viewing purposes:
{
"a":1,
"b":"string value",
"c":[
{
"Value":1
},
{
"Value":2,
"SubObject":[
{
"SubValue":3
}
]
}
]
}
*/
// Verify your JSON if you get any errors here
JsonValue json = JsonValue.Parse(jsonString);
// int test
if (json.ContainsKey("a"))
{
int a = json["a"]; // type already set to int
Console.WriteLine("json[\"a\"]" + " = " + a);
}
// string test
if (json.ContainsKey("b"))
{
string b = json["b"]; // type already set to string
Console.WriteLine("json[\"b\"]" + " = " + b);
}
// object array test
if (json.ContainsKey("c") && json["c"].JsonType == JsonType.Array)
{
// foreach loop test
foreach (JsonValue j in json["c"])
{
Console.WriteLine("j[\"Value\"]" + " = " + j["Value"].ToString());
}
// multi level key test
Console.WriteLine("json[\"c\"][0][\"Value\"]" + " = " + json["c"][0]["Value"].ToString());
Console.WriteLine("json[\"c\"][0][\"Value\"]" + " = " + json["c"][1]["Value"].ToString());
Console.WriteLine("json[\"c\"][1][\"SubObject\"][0][\"SubValue\"]" + " = " + json["c"][1]["SubObject"][0]["SubValue"].ToString());
}
Console.WriteLine();
Console.Write("Press any key to exit.");
Console.ReadKey();
}
}
}
Use this tool to generate a class based in your json:
http://json2csharp.com/
And then use the class to deserialize your json. Example:
public class Account
{
public string Email { get; set; }
public bool Active { get; set; }
public DateTime CreatedDate { get; set; }
public IList<string> Roles { get; set; }
}
string json = #"{
'Email': 'james#example.com',
'Active': true,
'CreatedDate': '2013-01-20T00:00:00Z',
'Roles': [
'User',
'Admin'
]
}";
Account account = JsonConvert.DeserializeObject<Account>(json);
Console.WriteLine(account.Email);
// james#example.com
References:
https://forums.asp.net/t/1992996.aspx?Nested+Json+Deserialization+to+C+object+and+using+that+object
https://www.newtonsoft.com/json/help/html/DeserializeObject.htm
Try the following code:
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("URL");
JArray array = new JArray();
using (var twitpicResponse = (HttpWebResponse)request.GetResponse())
using (var reader = new StreamReader(twitpicResponse.GetResponseStream()))
{
JavaScriptSerializer js = new JavaScriptSerializer();
var objText = reader.ReadToEnd();
JObject joResponse = JObject.Parse(objText);
JObject result = (JObject)joResponse["result"];
array = (JArray)result["Detail"];
string statu = array[0]["dlrStat"].ToString();
}
If JSON is dynamic as below
{
"Items": [{
"Name": "Apple",
"Price": 12.3
},
{
"Name": "Grape",
"Price": 3.21
}
],
"Date": "21/11/2010"
}
Then, Once you install NewtonSoft.Json from NuGet and include it in your project, you can serialize it as
string jsonString = "{\"Items\": [{\"Name\": \"Apple\",\"Price\": 12.3},{\"Name\": \"Grape\",\"Price\": 3.21}],\"Date\": \"21/11/2010\"}";
dynamic DynamicData = JsonConvert.DeserializeObject(jsonString);
Console.WriteLine( DynamicData.Date); // "21/11/2010"
Console.WriteLine(DynamicData.Items.Count); // 2
Console.WriteLine(DynamicData.Items[0].Name); // "Apple"
Source: How to read JSON data in C# (Example using Console app & ASP.NET MVC)?
The following from the msdn site should I think help provide some native functionality for what you are looking for. Please note it is specified for Windows 8. One such example from the site is listed below.
JsonValue jsonValue = JsonValue.Parse("{\"Width\": 800, \"Height\": 600, \"Title\": \"View from 15th Floor\", \"IDs\": [116, 943, 234, 38793]}");
double width = jsonValue.GetObject().GetNamedNumber("Width");
double height = jsonValue.GetObject().GetNamedNumber("Height");
string title = jsonValue.GetObject().GetNamedString("Title");
JsonArray ids = jsonValue.GetObject().GetNamedArray("IDs");
It utilizes the Windows.Data.JSON namespace.
Here's a complete, runnable example using csc v2.0.0.61501.
Packages:
nuget install Microsoft.AspNet.WebApi.Core
nuget install Microsoft.Net.Http
nuget install Newtonsoft.Json
Code:
using Newtonsoft.Json;
using System;
using System.Net.Http;
using System.Threading.Tasks;
public static class App
{
static void Main()
{
MainAsync().GetAwaiter().GetResult();
}
static async Task MainAsync()
{
string url = "https://httpbin.org/get";
var client = new HttpClient();
// The verbose way:
//HttpResponseMessage response = await client.GetAsync(url);
//response.EnsureSuccessStatusCode();
//string responseBody = await response.Content.ReadAsStringAsync();
// Or:
string responseBody = await client.GetStringAsync(url);
var obj = JsonConvert.DeserializeObject<dynamic>(responseBody);
Console.WriteLine(obj);
Console.WriteLine(obj.headers.Host);
}
}
Compiler command:
csc http_request2.cs -r:".\Microsoft.AspNet.WebApi.Core.5.2.9\lib\net45\System.Web.Http.dll" -r:".\Microsoft.Net.Http.2.2.29\lib\net40\System.Net.Http.dll" -r:".\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll"
Output:
{
"args": {},
"headers": {
"Host": "httpbin.org",
"X-Amzn-Trace-Id": "Root=1-633dce52-64f923bb42c99bf46f78672c"
},
"origin": "98.51.7.199",
"url": "https://httpbin.org/get"
}
httpbin.org
Per Could not load file or assembly Newtonsoft.json. The system cannot find the file specified, I had to move the Newtonsoft.Json.dll next to the compiled binary.
You can use following extentions
public static class JsonExtensions
{
public static T ToObject<T>(this string jsonText)
{
return JsonConvert.DeserializeObject<T>(jsonText);
}
public static string ToJson<T>(this T obj)
{
return JsonConvert.SerializeObject(obj);
}
}
I ended up with a simple class that creates types on the fly, instantiate them and hydrate them, mirroring the structure of the input JSON.
You can find it here:
https://github.com/starnutoditopo/JsonToObject
JsonToObjectConverter.cs
using System.Globalization;
using System.Reflection;
using System.Reflection.Emit;
using System.Text.Json;
namespace JsonToObject;
/// <summary>Provides functionalities to convert JSON strings in to CLR objects.</summary>
public class JsonToObjectConverter
{
private class Counter
{
private ulong count;
public Counter()
{
this.count = 0;
}
public ulong Next()
{
this.count++;
return this.count;
}
}
private static ulong assemblyGenerationCounter;
private readonly JsonToObjectConverterOptions options;
static JsonToObjectConverter()
{
assemblyGenerationCounter = 0;
}
/// <summary>
/// Initializes a new instance of the <see cref="JsonToObjectConverter" /> class, using default options.
/// </summary>
/// <param name="options">The options.</param>
public JsonToObjectConverter()
: this(new JsonToObjectConverterOptions())
{
}
/// <summary>
/// Initializes a new instance of the <see cref="JsonToObjectConverter" /> class, using the specified options.
/// </summary>
/// <param name="options">The options.</param>
public JsonToObjectConverter(JsonToObjectConverterOptions options)
{
this.options = options;
}
/// <summary>Converts a JSON string to an instance of a CLR object.</summary>
/// <param name="jsonString">The json string.</param>
/// <returns>
/// <br />
/// </returns>
public object? ConvertToObject(string jsonString)
{
JsonSerializerOptions opt = new JsonSerializerOptions()
{
PropertyNameCaseInsensitive = true
};
JsonElement rawResult = JsonSerializer.Deserialize<JsonElement>(jsonString, opt);
object? result = ToStronglyTypedObject(rawResult);
return result;
}
private object? ToStronglyTypedObject(JsonElement? nullableJsonElement)
{
string assemblyNameString;
ulong assemblyId = Interlocked.Increment(ref assemblyGenerationCounter);
try
{
assemblyNameString = string.Format(this.options.RuntimeGeneratedAssemblyNameTemplate, assemblyId.ToString(CultureInfo.InvariantCulture));
}
catch
{
throw new InvalidOperationException($#"Unable to generate assembly name using template '{this.options.RuntimeGeneratedAssemblyNameTemplate}' and id '{assemblyId}'. Please, review the {nameof(JsonToObjectConverterOptions.RuntimeGeneratedAssemblyNameTemplate)} property in the options.");
}
ModuleBuilder moduleBuilder = CreateModuleBuilder(assemblyNameString, this.options.RuntimeGeneratedModuleName);
Counter typeGenerationCounter = new Counter();
var result = ToStronglyTypedObject(nullableJsonElement, moduleBuilder, typeGenerationCounter);
return result;
}
private object? ToStronglyTypedObject(
JsonElement? nullableJsonElement,
ModuleBuilder moduleBuilder,
Counter typeGenerationCounter
)
{
if (nullableJsonElement == null)
{
return null;
}
JsonElement jsonElement = nullableJsonElement.Value;
switch (jsonElement.ValueKind)
{
case JsonValueKind.Undefined:
return null;
case JsonValueKind.String:
return jsonElement.GetString();
case JsonValueKind.False:
return false;
case JsonValueKind.True:
return true;
case JsonValueKind.Null:
return null;
case JsonValueKind.Number:
{
if (jsonElement.TryGetDouble(out var result))
{
return result;
}
}
throw new InvalidOperationException($"Unable to parse {jsonElement} as number.");
case JsonValueKind.Object:
{
ulong typeId = typeGenerationCounter.Next();
string typeName;
try
{
typeName = string.Format(this.options.RuntimeGeneratedTypeNameTemplate, typeId.ToString(CultureInfo.InvariantCulture));
}
catch
{
throw new InvalidOperationException($#"Unable to generate type name using template '{this.options.RuntimeGeneratedTypeNameTemplate}' and id '{typeId}'. Please, review the {nameof(JsonToObjectConverterOptions.RuntimeGeneratedTypeNameTemplate)} property in the options.");
}
TypeBuilder typeBuilder = CreateTypeBuilder(moduleBuilder, typeName);
Dictionary<string, object?> propertyValues = new Dictionary<string, object?>();
foreach (var property in jsonElement.EnumerateObject())
{
string propertyName = property.Name;
object? propertyValue = ToStronglyTypedObject(property.Value, moduleBuilder, typeGenerationCounter);
Type propertyValueType;
if (null == propertyValue)
{
propertyValueType = typeof(object);
}
else
{
propertyValueType = propertyValue.GetType();
}
CreateAutoImplementedProperty(typeBuilder, propertyName, propertyValueType);
propertyValues.Add(propertyName, propertyValue);
}
Type resultType = typeBuilder.CreateType()!;
object result = Activator.CreateInstance(resultType)!;
foreach (var pair in propertyValues)
{
var propertyInfo = resultType.GetProperty(pair.Key)!;
propertyInfo.SetValue(result, pair.Value);
}
return result;
}
case JsonValueKind.Array:
{
List<object?> list = new List<object?>();
foreach (var item in jsonElement.EnumerateArray())
{
object? value = ToStronglyTypedObject(item, moduleBuilder, typeGenerationCounter);
list.Add(value);
}
return list.ToArray();
}
default:
throw new InvalidOperationException($"Value type '{jsonElement.ValueKind}' is not supported");
}
}
private static ModuleBuilder CreateModuleBuilder(
string assemblyNameString,
string moduleName
)
{
// create assembly name
var assemblyName = new AssemblyName(assemblyNameString);
// create the assembly builder
AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
// create the module builder
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(moduleName);
return moduleBuilder;
}
private static TypeBuilder CreateTypeBuilder(
ModuleBuilder moduleBuilder,
string typeName
)
{
// create the type builder
TypeBuilder typeBuilder = moduleBuilder.DefineType(typeName, TypeAttributes.Public);
typeBuilder.DefineDefaultConstructor(MethodAttributes.Public);
return typeBuilder;
}
private static void CreateAutoImplementedProperty(
TypeBuilder builder,
string propertyName,
Type propertyType
)
{
const string PrivateFieldPrefix = "m_";
const string GetterPrefix = "get_";
const string SetterPrefix = "set_";
// Generate the field.
FieldBuilder fieldBuilder = builder.DefineField(
string.Concat(PrivateFieldPrefix, propertyName),
propertyType, FieldAttributes.Private);
// Generate the property
PropertyBuilder propertyBuilder = builder.DefineProperty(
propertyName, PropertyAttributes.HasDefault, propertyType, null);
// Property getter and setter attributes.
MethodAttributes propertyMethodAttributes =
MethodAttributes.Public | MethodAttributes.SpecialName |
MethodAttributes.HideBySig;
// Define the getter method.
MethodBuilder getterMethod = builder.DefineMethod(
string.Concat(GetterPrefix, propertyName),
propertyMethodAttributes, propertyType, Type.EmptyTypes);
// Emit the IL code.
// ldarg.0
// ldfld,_field
// ret
ILGenerator getterILCode = getterMethod.GetILGenerator();
getterILCode.Emit(OpCodes.Ldarg_0);
getterILCode.Emit(OpCodes.Ldfld, fieldBuilder);
getterILCode.Emit(OpCodes.Ret);
// Define the setter method.
MethodBuilder setterMethod = builder.DefineMethod(
string.Concat(SetterPrefix, propertyName),
propertyMethodAttributes, null, new Type[] { propertyType });
// Emit the IL code.
// ldarg.0
// ldarg.1
// stfld,_field
// ret
ILGenerator setterILCode = setterMethod.GetILGenerator();
setterILCode.Emit(OpCodes.Ldarg_0);
setterILCode.Emit(OpCodes.Ldarg_1);
setterILCode.Emit(OpCodes.Stfld, fieldBuilder);
setterILCode.Emit(OpCodes.Ret);
propertyBuilder.SetGetMethod(getterMethod);
propertyBuilder.SetSetMethod(setterMethod);
}
}
JsonToObjectConverterOptions.cs
namespace JsonToObject;
/// <summary>
/// Defines the options to instantiate a <see cref="JsonToObjectConverter" /> object.
/// </summary>
public class JsonToObjectConverterOptions
{
private const string CONSTANTS_RuntimeGeneratedModuleName = $"RuntimeGeneratedModule";
private const string CONSTANTS_RuntimeGeneratedAssemblyNameTemplate = "RuntimeGeneratedAssembly_{0}";
private const string CONSTANTS_RuntimeGeneratedTypeNameTemplate = "RuntimeGeneratedType_{0}";
/// <summary>Gets or sets the name of the runtime-generated module.</summary>
/// <value>The name of the runtime-generated module.</value>
public string RuntimeGeneratedModuleName { get; set; } = CONSTANTS_RuntimeGeneratedModuleName;
/// <summary>Gets or sets the template to use to generate the name of runtime-generated assemblies.</summary>
/// <value>The template to use to generate the name of runtime-generated assemblies.</value>
/// <remarks>Should contain a "{0}" placeholder.</remarks>
public string RuntimeGeneratedAssemblyNameTemplate { get; set; } = CONSTANTS_RuntimeGeneratedAssemblyNameTemplate;
/// <summary>Gets or sets the template to use to generate the name of runtime-generated types.</summary>
/// <value>The template to use to generate the name of runtime-generated types.</value>
/// <remarks>Should contain a "{0}" placeholder.</remarks>
public string RuntimeGeneratedTypeNameTemplate { get; set; } = CONSTANTS_RuntimeGeneratedTypeNameTemplate;
}
I think the best answer that I've seen has been #MD_Sayem_Ahmed.
Your question is "How can I parse Json with C#", but it seems like you are wanting to decode Json. If you are wanting to decode it, Ahmed's answer is good.
If you are trying to accomplish this in ASP.NET Web Api, the easiest way is to create a data transfer object that holds the data you want to assign:
public class MyDto{
public string Name{get; set;}
public string Value{get; set;}
}
You have simply add the application/json header to your request (if you are using Fiddler, for example).
You would then use this in ASP.NET Web API as follows:
//controller method -- assuming you want to post and return data
public MyDto Post([FromBody] MyDto myDto){
MyDto someDto = myDto;
/*ASP.NET automatically converts the data for you into this object
if you post a json object as follows:
{
"Name": "SomeName",
"Value": "SomeValue"
}
*/
//do some stuff
}
This helped me a lot when I was working in my Web Api and made my life super easy.
string json = #"{
'Name': 'Wide Web',
'Url': 'www.wideweb.com.br'}";
JavaScriptSerializer jsonSerializer = new JavaScriptSerializer();
dynamic j = jsonSerializer.Deserialize<dynamic>(json);
string name = j["Name"].ToString();
string url = j["Url"].ToString();
var result = controller.ActioName(objParams);
IDictionary<string, object> data = (IDictionary<string, object>)new System.Web.Routing.RouteValueDictionary(result.Data);
Assert.AreEqual("Table already exists.", data["Message"]);
using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(user)))
{
// Deserialization from JSON
DataContractJsonSerializer deserializer = new DataContractJsonSerializer(typeof(UserListing))
DataContractJsonSerializer(typeof(UserListing));
UserListing response = (UserListing)deserializer.ReadObject(ms);
}
public class UserListing
{
public List<UserList> users { get; set; }
}
public class UserList
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
I have a web api controller in .NET Core 2.1, which receives
JToken jsonBody
The json has the following structure
{
"id": "xxx",
"payload": {
"TelephoneNumber": "1111",
"Name": "Hans"
}
}
and more fields, but it's irrelevant.
I want to retrieve the Number and Name elegantly. Currently, I do the following, which I'm sure could be done in a nicer way:
var payload = JObject.Parse(jsonBody.SelectToken("Payload").ToString());
telephoneNumber = new TelephoneNumber(payload.SelectToken("TelephoneNumber").ToString());
I've tried just doing
jsonBody.SelectToken("Payload.TelephoneNumber")
but that doesn't work. I think that it's because somehow the jsonBody, that the controller receives, has only parsed the top nodes as json, hence it could be that it regards the value of
jsonBody.SelectToken("Payload")
as a string.
As per official documentation - you can do something like this:
var phone = jsonBody["payload"]["TelephoneNumber"].ToString();
var name = jsonBody["payload"]["Name"].ToString();
See a live demo on rextester.
This is at least a little bit more elegant:
var jsonBody = JObject.Parse(#"{
'id': 'xxx',
'payload': {
'TelephoneNumber': '1111',
'Name': 'Hans'
}
}");
var phone = jsonBody["payload"]["TelephoneNumber"].Value<string>();
var name = jsonBody["payload"]["Name"].Value<string>();
If you don't want to deserialize your full json, you can create a class with the properties you need
public class Payload
{
public string TelephoneNumber { get; set; }
public string Name { get; set; }
}
And then use JsonTextReader to deserialize the string:
private static Payload DeserializePayload(JToken token)
{
var serializer = new JsonSerializer();
using (JsonTextReader reader = new JsonTextReader(new StringReader(token.ToString())))
{
reader.CloseInput = true;
while (reader.Read())
{
if (reader.TokenType == JsonToken.StartObject && reader.Path.Equals("payload"))
{
var payload = serializer.Deserialize<Payload>(reader);
return payload;
}
}
}
// not found - return null? throw exception?
return null;
}
Testing the code:
var token = JToken.Parse(#"{
""id"": ""xxx"",
""payload"": {
""TelephoneNumber"": ""1111"",
""Name"": ""Hans""
}
}");
Payload payload = DeserializePayload(token);
Console.WriteLine($"Name: {payload.Name}, Phone number: {payload.TelephoneNumber}");
I want to make a POST request to the Hubspot API (https://developers.hubspot.com/docs/methods/contacts/create_or_update) and I need the JSON to match this format:
{ "properties": [ { "property": "firstname", "value": "HubSpot" } ] }
Instead im getting this:
{ "properties": [ { "Key": "email", "Value": "alphatest#baconcompany.com" }, { "Key": "firstname", "Value": "testfirstname" } ] }
Instead of "property" and "value" , my code generates "Key" and "Value" , how can I change my JSON to match the right format?
Here is how I generate that dictionary:
public class HubspotContact
{
public Dictionary<string, string> properties { get; set; }
}
private static readonly HttpClient client = new HttpClient();
class DictionaryAsArrayResolver : DefaultContractResolver
{
protected override JsonContract CreateContract(Type objectType)
{
if (objectType.GetInterfaces().Any(i => i == typeof(IDictionary) ||
(i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IDictionary<,>))))
{
return base.CreateArrayContract(objectType);
}
return base.CreateContract(objectType);
}
}
And this is how I generate the JSON:
HubspotContact foo = new HubspotContact();
foo.properties = new Dictionary<string, string>();
foo.properties.Add("email", "alphatest#baconcompany.com");
foo.properties.Add("firstname", "firstname");
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.Formatting = Formatting.Indented;
settings.ContractResolver = new DictionaryAsArrayResolver();
string json = JsonConvert.SerializeObject(foo, settings);
Finally this is how I send my request:
var httpWebRequest =(HttpWebRequest)WebRequest.Create("https://api.hubapi.com/contacts/v1/contact/createOrUpdate/email/alphatest#baconcompany.com/?hapikey=myapikey");
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = "POST";
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream())){
streamWriter.Write(json);
streamWriter.Flush();
streamWriter.Close();
}
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
Console.WriteLine(result.ToString());
}
Right now with the request as is I get this error:
System.Net.WebException: 'The remote server returned an error: (400) Bad Request.'
Change HubspotContact to this:
class PropertyValue
{
public string Property { get;set;}
public string Value { get;set;}
}
class HubspotContact
{
public List<PropertyValue> Properties {get;set;}
}
It should serialize to a proper format and it does not need custom serializer.
C#'s Json serializer does not support custom naming of properties coming from any generic data structure...
Try replacing the Dictionary with a custom class containing the properties "property" and "value" instead.
I have written these lines of code which make an API request and in return I get valid JSON response:
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(_baseAddress);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.GetAsync(_apiUrl);
if (response.IsSuccessStatusCode)
{
var data = await response.Content.ReadAsAsync<ExpandoObject>();
return Json(data);
}
}
The data looks like below:
Is it possible to get the value of ProductID and Price. I want to assign them to something like:
int productId = ...
int price = ...
How can i do this using C#?
Check out the Newtonsoft Json nuget package. Basically, you create an model with the variables you need, then you call the deserialize method from Newtonsoft. Here's some pseudo code
public class MyObject
{
int ProductID { get; set; }
int Price { get; set; }
int Systems { get; set; }
}
Then in your method:
using Newtonsoft.Json;
public class MyMethod(string json)
{
MyObject obj = JsonConvert.DeserializeObject<MyObject>(json);
}
Something like that.
.Net 4.0 supports creating dynamic objects directly from json:
JavaScriptSerializer serializer = new JavaScriptSerializer();
dynamic item = serializer.Deserialize<object>("{ \"productId\":\"124889\" }");
string test= item["productId"];
If your using Json.NET or Newtonsoft.Json.Linq - this answer should help you.
Json.Net
dynamic stuff = JsonConvert.DeserializeObject("{ 'Name': 'Jon Smith', 'Address': { 'City': 'New York', 'State': 'NY' }, 'Age': 42 }");
string name = stuff.Name;
string address = stuff.Address.City;
Newtonsoft.Json.Linq
dynamic stuff = JObject.Parse("{ 'Name': 'Jon Smith', 'Address': { 'City': 'New York', 'State': 'NY' }, 'Age': 42 }");
string name = stuff.Name;
string address = stuff.Address.City;
string name = stuff.Name;
string address = stuff.Address.City;
I am sorry to answer to my own question but I just found the solution and i wanted to post here:
You need to add these lines of code after data
var _dataResponse = JToken.Parse(JsonConvert.SerializeObject(data));
var _dataResponseProductID = _dataResponse["ProductID"];
var _dataResponsePrice = _dataResponse["Price"];
After that the values taken can be converted to desired data types.
Create an object and Deserialize the json object.
http://www.newtonsoft.com/json/help/html/t_newtonsoft_json_jsonconvert.htm
The JSON Schema draft specification describes the use of the $schema keyword "as a JSON Schema version identifier and the location of a resource which is itself a JSON Schema." However, when I attempted to verify the draft v3 and v4 support I was unable to see the $schema value being considered. As an example, consider the below test fixture.
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Schema;
using NUnit.Framework;
using System.Collections.Generic;
using System.IO;
namespace JsonSchemaExamples
{
[TestFixture]
public class ValidatorPlay
{
#region schema definitions
private const string myV4Schema = #"{
'$schema': 'http://json-schema.org/draft-04/schema#',
'type': 'object',
'properties':
{
'first_name': { 'type': 'string' },
'address':
{
'type': 'object',
'properties':
{
'street_address': { 'type': 'string' },
'state': { 'type': 'string' }
}
}
},
'required' : ['first_name']
}";
private const string myV3Schema = #"{
'$schema': 'http://json-schema.org/draft-03/schema#',
'type': 'object',
'properties':
{
'first_name':
{
'type': 'string',
'required': true
},
'address':
{
'type': 'object',
'properties':
{
'street_address': { 'type': 'string' },
'state': { 'type': 'string' }
}
}
}
}";
#endregion
#region json to validate
private JObject validPerson = JObject.Parse(#"{
'first_name' : 'Mark',
'age': 32,
'address' :
{
'street': '1 Main Street',
'postcode': 'AB12 0CD'
}
}");
private JObject invalidPerson = JObject.Parse(#"{
'Name' : 'Mark',
'age': 32,
'address' :
{
'street': '1 Main Street',
'postcode': 'AB12 0CD'
}
}");
#endregion
[TestCase(myV4Schema)]
[TestCase(myV3Schema)]
public void CheckDraftSupport(string schemaToUse)
{
JSchemaUrlResolver resolver = new JSchemaUrlResolver();
JSchema schema = JSchema.Parse(schemaToUse, resolver);
Assert.That(validPerson.IsValid(schema));
Assert.That(!invalidPerson.IsValid(schema));
}
}
}
If I change the $schema values within myV4Schema to point to v3 or vice versa with myV3Schema both my tests continue to pass. I would have expected them to fail and report a malformed schema (due to the required attribute).
What have I misunderstood or what am I doing wrong?
Validation that a schema meets the spec using "$schema" will come soon in a future version. Right now both V3 and V4 are always supported.
Update:
$schema is used in the latest version on NuGet.