I have this JSON Array as input.
[
{
"FirstName": "Test1",
"LastName": "Test2",
"Address": "London, GB",
"Error": "Something's gone wrong"
},
{
"FirstName": "Test3",
"LastName": "Test4",
"Address": "NewYork, US",
"Error": "Something's gone wrong"
},
{
"DisplayName": "ContactNumber",
"Value": "01234 123 123"
}
]
I want to build a JSON Object like this in C#
[
"pages":{
"FirstName": "Test1",
"LastName": "Test2",
"Address": "London, GB",
"Error": "Something's gone wrong"
},
{
"FirstName": "Test3",
"LastName": "Test4",
"Address": "NewYork, US",
"Error": "Something's gone wrong"
},
"labels": {
"DisplayName": "ContactNumber",
"Value": "01234 123 123"
}
}
]
I've created a Model with above output properties but they are not getting mapped when I deserialize the object into that Model. All values are returning null.
var deserializedData = JsonConvert.DeserializeObject<List<Config>>(serializedData);
the response I receive when I check is
[
{
"pages": null,
"labels": null
},
{
"pages": null,
"labels": null
}
]
Can anyone help me build the Custom Model for this format I want in C#.
Thanks in advance.
What you have is a polymorphic JSON array containing a variety of types of objects, distinguishable by the presence of specific properties ("DisplayName" vs "FirstName", e.g.). What you would like to do is to deserialize that into a c# model in which each possible array item gets added to a collection-valued property of your model, where the collection property is chosen to have the correct item type.
This can be accomplished by using a custom JsonConverter. Since the problem statement is generic I'm going to make the converter be generic. A hardcoded converter would require less code.
First, define your desired model as follows:
public class Page
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address { get; set; }
public string Error { get; set; }
}
public class Label
{
public string DisplayName { get; set; }
public string Value { get; set; }
}
public class RootObject
{
public List<Page> pages { get; set; }
public List<Label> labels { get; set; }
}
Next define the following converter:
public class PolymorphicArrayToObjectConverter<TObject> : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof(TObject).IsAssignableFrom(objectType);
}
public override bool CanWrite { get { return false; } }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
static JsonObjectContract FindContract(JObject obj, IEnumerable<Type> derivedTypes, JsonSerializer serializer)
{
List<JsonObjectContract> bestContracts = new List<JsonObjectContract>();
foreach (var type in derivedTypes)
{
if (type.IsAbstract)
continue;
var contract = serializer.ContractResolver.ResolveContract(type) as JsonObjectContract;
if (contract == null)
continue;
if (obj.Properties().Select(p => p.Name).Any(n => contract.Properties.GetClosestMatchProperty(n) == null))
continue;
if (bestContracts.Count == 0 || bestContracts[0].Properties.Count > contract.Properties.Count)
{
bestContracts.Clear();
bestContracts.Add(contract);
}
else if (contract.Properties.Count == bestContracts[0].Properties.Count)
{
bestContracts.Add(contract);
}
}
return bestContracts.Single();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
else if (reader.TokenType != JsonToken.StartArray)
throw new InvalidOperationException("JSON token is not an array at path: " + reader.Path);
var contract = (JsonObjectContract)serializer.ContractResolver.ResolveContract(objectType);
existingValue = existingValue ?? contract.DefaultCreator();
var lookup = contract
.Properties
.Select(p => new { Property = p, PropertyContract = serializer.ContractResolver.ResolveContract(p.PropertyType) as JsonArrayContract })
.Where(i => i.PropertyContract != null)
.ToDictionary(i => i.PropertyContract.CollectionItemType);
var types = lookup.Select(i => i.Key).ToList();
while (reader.Read())
{
switch (reader.TokenType)
{
case JsonToken.Comment:
break;
case JsonToken.EndArray:
return existingValue;
default:
{
var itemObj = JObject.Load(reader);
var itemContract = FindContract(itemObj, types, serializer);
if (itemContract == null)
continue;
var item = serializer.Deserialize(itemObj.CreateReader(), itemContract.UnderlyingType);
var propertyData = lookup[itemContract.UnderlyingType];
var collection = propertyData.Property.ValueProvider.GetValue(existingValue);
if (collection == null)
{
collection = propertyData.PropertyContract.DefaultCreator();
propertyData.Property.ValueProvider.SetValue(existingValue, collection);
}
collection.GetType().GetMethod("Add").Invoke(collection, new [] { item });
}
break;
}
}
// Should not come here.
throw new JsonSerializationException("Unclosed array at path: " + reader.Path);
}
}
Then, deserialize and re-serialize your RootObject collection as follows:
var settings = new JsonSerializerSettings
{
Converters = { new PolymorphicArrayToObjectConverter<RootObject>() },
};
var root = new List<RootObject> { JsonConvert.DeserializeObject<RootObject>(jsonString, settings) };
var outputJson = JsonConvert.SerializeObject(root, Formatting.Indented);
As a result, the following JSON will be generated:
[
{
"pages": [
{
"FirstName": "Test1",
"LastName": "Test2",
"Address": "London, GB",
"Error": "Something's gone wrong"
},
{
"FirstName": "Test3",
"LastName": "Test4",
"Address": "NewYork, US",
"Error": "Something's gone wrong"
}
],
"labels": [
{
"DisplayName": "ContactNumber",
"Value": "01234 123 123"
}
]
}
]
Sample fiddle.
Note - code to automatically infer the array item type was adapted from this answer.
you json is not valid json structure for parsing , this not valid at all(check what is wrong with it here : https://jsonlint.com/)
not valid json string given by you
[
"pages":{
"FirstName": "Test1",
"LastName": "Test2",
"Address": "London, GB",
"Error": "Something's gone wrong"
},
{
"FirstName": "Test3",
"LastName": "Test4",
"Address": "NewYork, US",
"Error": "Something's gone wrong"
},
"labels": {
"DisplayName": "ContactNumber",
"Value": "01234 123 123"
}
}
]
However I fixed json you given
Fixed and working json
[{
"pages": [{
"FirstName": "Test1",
"LastName": "Test2",
"Address": "London, GB",
"Error": "Something's gone wrong"
},
{
"FirstName": "Test3",
"LastName": "Test4",
"Address": "NewYork, US",
"Error": "Something's gone wrong"
}
],
"labels": {
"DisplayName": "ContactNumber",
"Value": "01234 123 123"
}
}]
After applying fix json , your C# object is
public class Page
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address { get; set; }
public string Error { get; set; }
}
public class Labels
{
public string DisplayName { get; set; }
public string Value { get; set; }
}
public class RootObject
{
public List<Page> pages { get; set; }
public Labels labels { get; set; }
}
and I tried this with my fixed json and its working fine.
End of Edit
Below code is working fine for me with the class structure i provided you in below
for list
var jsonString = "[{ \"pages\": {\"id\": 12345, \"name\": \"John Doe\", \"number\": \"123\", \"test\": "+
"\"John\" }, \"labels\": { \"test\": \"test1\", \"test2\": \"test2\" } }," +
"{ \"pages\": {\"id\": 12345, \"name\": \"John Doe\", \"number\": \"123\", \"test\": "+
"\"John\" }, \"labels\": { \"test\": \"test1\", \"test2\": \"test2\" } }]";
var deserializedData = JsonConvert.DeserializeObject<List<RootObject>>(jsonString);
With single object as input
var jsonString = "{ \"pages\": {\"id\": 12345, \"name\": \"John Doe\", \"number\": \"123\", \"test\": "+
"\"John\" }, \"labels\": { \"test\": \"test1\", \"test2\": \"test2\" } }";
var deserializedData = JsonConvert.DeserializeObject<RootObject>(jsonString);
based on input
{ "pages": { "id": 12345, "name": "John Doe", "number": "123", "test":
"John" }, "labels": { "test": "test1", "test2": "test2" } }
below is generated classes
public class Pages
{
public int id { get; set; }
public string name { get; set; }
public string number { get; set; }
public string test { get; set; }
}
public class Labels
{
public string test { get; set; }
public string test2 { get; set; }
}
public class RootObject
{
public Pages pages { get; set; }
public Labels labels { get; set; }
}
If you have Json with you than you can generate C# class using visual studio itself.
In visual studio Find "Paste Sepcial" menu. i.e. copy you json string and click on Paste special , it will generate C# class for you.
you can follow my post : Generate Class From JSON or XML in Visual Studio
or use online website like : json2csharp
Related
I am having trouble deserializing JSON received from HubSpot ContactList API.
I am using Restsharp and NewtonSoft, and I'm having real struggles understanding how to correctly define the required classes in order to deserialize the JSON string, which is below:
"contacts": [
{
"vid": 2251,
"portal-id": 5532227,
"is-contact": true,
"profile-url": "https://app.hubspot.com/contacts/5532227/contact/2251",
"properties": {
"firstname": {
"value": "Carl"
},
"lastmodifieddate": {
"value": "1554898386040"
},
"company": {
"value": "Cygnus Project"
},
"lastname": {
"value": "Swann"
}
},
"form-submissions": [],
"identity-profiles": [
{
"vid": 2251,
"saved-at-timestamp": 1553635648634,
"deleted-changed-timestamp": 0,
"identities": [
{
"type": "EMAIL",
"value": "cswann#cygnus.co.uk",
"timestamp": 1553635648591,
"is-primary": true
},
{
"type": "LEAD_GUID",
"value": "e2345",
"timestamp": 1553635648630
}
]
}
],
"merge-audits": []
},
{
"vid": 2301,
"portal-id": 5532227,
"is-contact": true,
"profile-url": "https://app.hubspot.com/contacts/5532227/contact/2301",
"properties": {
"firstname": {
"value": "Carlos"
},
"lastmodifieddate": {
"value": "1554886333954"
},
"company": {
"value": "Khaos Control"
},
"lastname": {
"value": "Swannington"
}
},
"identity-profiles": [
{
"vid": 2301,
"saved-at-timestamp": 1553635648733,
"deleted-changed-timestamp": 0,
"identities": [
{
"type": "EMAIL",
"value": "cswann#khaoscontrol.com",
"timestamp": 1553635648578,
"is-primary": true
},
{
"type": "LEAD_GUID",
"value": "c7f403ba",
"timestamp": 1553635648729
}
]
}
],
"merge-audits": []
}
],
"has-more": false,
"vid-offset": 2401
}
If I simply request the vid, I correctly get 2 vid's back. It's when I try to do the properties and that i get a fail.
Please help
Lets reduce the Json to the minimum to reproduce your error :
{
"vid": 2301,
"portal-id": 5532227,
"is-contact": true,
"profile-url": "https://app.hubspot.com/contacts/5532227/contact/2301",
"properties": {
"firstname": {
"value": "Carlos"
},
"lastmodifieddate": {
"value": "1554886333954"
},
"company": {
"value": "Khaos Control"
},
"lastname": {
"value": "Swannington"
}
}
}
And the appropriate class ContactListAPI_Result:
public partial class ContactListAPI_Result
{
[JsonProperty("vid")]
public long Vid { get; set; }
[JsonProperty("portal-id")]
public long PortalId { get; set; }
[JsonProperty("is-contact")]
public bool IsContact { get; set; }
[JsonProperty("profile-url")]
public Uri ProfileUrl { get; set; }
[JsonProperty("properties")]
public Dictionary<string, Dictionary<string, string>> Properties { get; set; }
}
public partial class ContactListAPI_Result
{
public static ContactListAPI_Result FromJson(string json)
=> JsonConvert.DeserializeObject<ContactListAPI_Result>(json);
//public static ContactListAPI_Result FromJson(string json)
// => JsonConvert.DeserializeObject<ContactListAPI_Result>(json, Converter.Settings);
}
public static void toto()
{
string input = #" {
""vid"": 2301,
""portal-id"": 5532227,
""is-contact"": true,
""profile-url"": ""https://app.hubspot.com/contacts/5532227/contact/2301"",
""properties"": {
""firstname"": {
""value"": ""Carlos""
},
""lastmodifieddate"": {
""value"": ""1554886333954""
},
""company"": {
""value"": ""Khaos Control""
},
""lastname"": {
""value"": ""Swannington""
}
}
}";
var foo = ContactListAPI_Result.FromJson(input);
}
But the Value of one property will be burrow in the sub dictionary, we can the project the object in a more usefull one :
public partial class ItemDTO
{
public long Vid { get; set; }
public long PortalId { get; set; }
public bool IsContact { get; set; }
public Uri ProfileUrl { get; set; }
public Dictionary<string, string> Properties { get; set; }
}
Adding the projection to the Class:
public ItemDTO ToDTO()
{
return new ItemDTO
{
Vid = Vid,
PortalId = PortalId,
IsContact = IsContact,
ProfileUrl = ProfileUrl,
Properties =
Properties.ToDictionary(
p => p.Key,
p => p.Value["value"]
)
};
}
Usage :
var result = foo.ToDTO();
Live Demo
Creating and managing class structure for big and nested key/value pair json is tedious task
So one approach is to use JToken instead.
You can simply parse your JSON to JToken and by querying parsed object, you will easily read the data that you want without creating class structure for your json
From your post it seems you need to retrieve vid and properties from your json so try below code,
string json = "Your json here";
JToken jToken = JToken.Parse(json);
var result = jToken["contacts"].ToObject<JArray>()
.Select(x => new
{
vid = Convert.ToInt32(x["vid"]),
properties = x["properties"].ToObject<Dictionary<string, JToken>>()
.Select(y => new
{
Key = y.Key,
Value = y.Value["value"].ToString()
}).ToList()
}).ToList();
//-----------Print the result to console------------
foreach (var item in result)
{
Console.WriteLine(item.vid);
foreach (var prop in item.properties)
{
Console.WriteLine(prop.Key + " - " + prop.Value);
}
Console.WriteLine();
}
Output:
OK. I have sent a GET request to SharePoint and received a string back:
"{\"#odata.context\":\"https://graph.microsoft.com/v1.0/$metadata#sites('XXXXX.sharepoint.com%2C495435b4-60c3-49b7-8f6e-1d262a120ae5%2C0fad9f67-35a8-4c0b-892e-113084058c0a')/lists('18a725ac-83ef-48fb-a5cb-950ca2378fd0')/items\",\"value\":[{\"#odata.etag\":\"\\\"a69b1840-239d-42ed-9b20-8789761fb06a,3\\\"\",\"createdDateTime\":\"2018-08-25T22:44:16Z\",\"eTag\":\"\\\"a69b1840-239d-42ed-9b20-8789761fb06a,3\\\"\",\"id\":\"9\",\"lastModifiedDateTime\":\"2018-08-25T22:44:16Z\",\"webUrl\":\"https://XXXXX.sharepoint.com/sites/GeneratorApp/Lists/GenApp/9_.000\",\"createdBy\":{\"user\":{\"email\":\"XXXXX#XXXXX.com\",\"id\":\"b0465821-e891-4f44-9e18-27e875f1b75d\",\"displayName\":\"XXXXX\"}},\"lastModifiedBy\":{\"user\":{\"email\":\"XXXXX#XXXXX.com\",\"id\":\"b0465821-e891-4f44-9e18-27e875f1b75d\",\"displayName\":\"XXXXX\"}},\"parentReference\":{},\"contentType\":{\"id\":\"0x0100E19591A4ECA81542AEA41A6AAFED6781\"},\"fields#odata.context\":\"https://graph.microsoft.com/v1.0/$metadata#sites('XXXXX.sharepoint.com%2C495435b4-60c3-49b7-8f6e-1d262a120ae5%2C0fad9f67-35a8-4c0b-892e-113084058c0a')/lists('18a725ac-83ef-48fb-a5cb-950ca2378fd0')/items('9')/fields/$entity\",\"fields\":{\"#odata.etag\":\"\\\"a69b1840-239d-42ed-9b20-8789761fb06a,3\\\"\",\"SerialNumber\":\"20180824-1353-DC6-Generator-A\",\"id\":\"9\"}},{\"#odata.etag\":\"\\\"13f60f9e-1bf2-4803-93b9-c45234963d47,3\\\"\",\"createdDateTime\":\"2018-08-25T22:45:55Z\",\"eTag\":\"\\\"13f60f9e-1bf2-4803-93b9-c45234963d47,3\\\"\",\"id\":\"10\",\"lastModifiedDateTime\":\"2018-08-25T22:45:55Z\",\"webUrl\":\"https://XXXXX.sharepoint.com/sites/GeneratorApp/Lists/GenApp/10_.000\",\"createdBy\":{\"user\":{\"email\":\"XXXXX#XXXXX.com\",\"id\":\"b0465821-e891-4f44-9e18-27e875f1b75d\",\"displayName\":\"XXXXX\"}},\"lastModifiedBy\":{\"user\":{\"email\":\"XXXXX#XXXXX.com\",\"id\":\"b0465821-e891-4f44-9e18-27e875f1b75d\",\"displayName\":\"XXXXX\"}},\"parentReference\":{},\"contentType\":{\"id\":\"0x0100E19591A4ECA81542AEA41A6AAFED6781\"},\"fields#odata.context\":\"https://graph.microsoft.com/v1.0/$metadata#sites('XXXXX.sharepoint.com%2C495435b4-60c3-49b7-8f6e-1d262a120ae5%2C0fad9f67-35a8-4c0b-892e-113084058c0a')/lists('18a725ac-83ef-48fb-a5cb-950ca2378fd0')/items('10')/fields/$entity\",\"fields\":{\"#odata.etag\":\"\\\"13f60f9e-1bf2-4803-93b9-c45234963d47,3\\\"\",\"SerialNumber\":\"20180824-1416-DC6-Generator-B\",\"id\":\"10\"}},{\"#odata.etag\":\"\\\"00024848-0d4e-4ee8-b018-f1653af2a577,3\\\"\",\"createdDateTime\":\"2018-08-25T22:47:30Z\",\"eTag\":\"\\\"00024848-0d4e-4ee8-b018-f1653af2a577,3\\\"\",\"id\":\"11\",\"lastModifiedDateTime\":\"2018-08-25T22:47:30Z\",\"webUrl\":\"https://XXXXX.sharepoint.com/sites/GeneratorApp/Lists/GenApp/11_.000\",\"createdBy\":{\"user\":{\"email\":\"XXXXX#XXXXX.com\",\"id\":\"b0465821-e891-4f44-9e18-27e875f1b75d\",\"displayName\":\"XXXXX\"}},\"lastModifiedBy\":{\"user\":{\"email\":\"XXXXX#XXXXX.com\",\"id\":\"b0465821-e891-4f44-9e18-27e875f1b75d\",\"displayName\":\"XXXXX\"}},\"parentReference\":{},\"contentType\":{\"id\":\"0x0100E19591A4ECA81542AEA41A6AAFED6781\"},\"fields#odata.context\":\"https://graph.microsoft.com/v1.0/$metadata#sites('XXXXX.sharepoint.com%2C495435b4-60c3-49b7-8f6e-1d262a120ae5%2C0fad9f67-35a8-4c0b-892e-113084058c0a')/lists('18a725ac-83ef-48fb-a5cb-950ca2378fd0')/items('11')/fields/$entity\",\"fields\":{\"#odata.etag\":\"\\\"00024848-0d4e-4ee8-b018-f1653af2a577,3\\\"\",\"SerialNumber\":\"20180824-1438-DC6-Generator-R\",\"id\":\"11\"}},{\"#odata.etag\":\"\\\"7c8e80ed-6fea-408a-9594-2b7b13e3691b,3\\\"\",\"createdDateTime\":\"2018-08-25T23:02:43Z\",\"eTag\":\"\\\"7c8e80ed-6fea-408a-9594-2b7b13e3691b,3\\\"\",\"id\":\"12\",\"lastModifiedDateTime\":\"2018-08-25T23:02:43Z\",\"webUrl\":\"https://XXXXX.sharepoint.com/sites/GeneratorApp/Lists/GenApp/12_.000\",\"createdBy\":{\"user\":{\"email\":\"XXXXX#XXXXX.com\",\"id\":\"b0465821-e891-4f44-9e18-27e875f1b75d\",\"displayName\":\"XXXXX\"}},\"lastModifiedBy\":{\"user\":{\"email\":\"XXXXX#XXXXX.com\",\"id\":\"b0465821-e891-4f44-9e18-27e875f1b75d\",\"displayName\":\"XXXXX\"}},\"parentReference\":{},\"contentType\":{\"id\":\"0x0100E19591A4ECA81542AEA41A6AAFED6781\"},\"fields#odata.context\":\"https://graph.microsoft.com/v1.0/$metadata#sites('XXXXX.sharepoint.com%2C495435b4-60c3-49b7-8f6e-1d262a120ae5%2C0fad9f67-35a8-4c0b-892e-113084058c0a')/lists('18a725ac-83ef-48fb-a5cb-950ca2378fd0')/items('12')/fields/$entity\",\"fields\":{\"#odata.etag\":\"\\\"7c8e80ed-6fea-408a-9594-2b7b13e3691b,3\\\"\",\"SerialNumber\":\"20180824-1456-DC6-Generator-C\",\"id\":\"12\"}}]}"
Which will JObject.Parse to this:
{{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#sites('XXXXX.sharepoint.com%2C495435b4-60c3-49b7-8f6e-1d262a120ae5%2C0fad9f67-35a8-4c0b-892e-113084058c0a')/lists('18a725ac-83ef-48fb-a5cb-950ca2378fd0')/items",
"value": [
{
"#odata.etag": "\"a69b1840-239d-42ed-9b20-8789761fb06a,3\"",
"createdDateTime": "2018-08-25T22:44:16Z",
"eTag": "\"a69b1840-239d-42ed-9b20-8789761fb06a,3\"",
"id": "9",
"lastModifiedDateTime": "2018-08-25T22:44:16Z",
"webUrl": "https://XXXXX.sharepoint.com/sites/GeneratorApp/Lists/GenApp/9_.000",
"createdBy": {
"user": {
"email": "XXXXX#XXXXX.com",
"id": "b0465821-e891-4f44-9e18-27e875f1b75d",
"displayName": "XXXXX"
}
},
"lastModifiedBy": {
"user": {
"email": "XXXXX#XXXXX.com",
"id": "b0465821-e891-4f44-9e18-27e875f1b75d",
"displayName": "XXXXX"
}
},
"parentReference": {},
"contentType": {
"id": "0x0100E19591A4ECA81542AEA41A6AAFED6781"
},
"fields#odata.context": "https://graph.microsoft.com/v1.0/$metadata#sites('XXXXX.sharepoint.com%2C495435b4-60c3-49b7-8f6e-1d262a120ae5%2C0fad9f67-35a8-4c0b-892e-113084058c0a')/lists('18a725ac-83ef-48fb-a5cb-950ca2378fd0')/items('9')/fields/$entity",
"fields": {
"#odata.etag": "\"a69b1840-239d-42ed-9b20-8789761fb06a,3\"",
"SerialNumber": "20180824-1353-DC6-Generator-A",
"id": "9"
}
},
{
"#odata.etag": "\"13f60f9e-1bf2-4803-93b9-c45234963d47,3\"",
"createdDateTime": "2018-08-25T22:45:55Z",
"eTag": "\"13f60f9e-1bf2-4803-93b9-c45234963d47,3\"",
"id": "10",
"lastModifiedDateTime": "2018-08-25T22:45:55Z",
"webUrl": "https://XXXXX.sharepoint.com/sites/GeneratorApp/Lists/GenApp/10_.000",
"createdBy": {
"user": {
"email": "XXXXX#XXXXX.com",
"id": "b0465821-e891-4f44-9e18-27e875f1b75d",
"displayName": "XXXXX"
}
},
"lastModifiedBy": {
"user": {
"email": "XXXXX#XXXXX.com",
"id": "b0465821-e891-4f44-9e18-27e875f1b75d",
"displayName": "XXXXX"
}
},
"parentReference": {},
"contentType": {
"id": "0x0100E19591A4ECA81542AEA41A6AAFED6781"
},
"fields#odata.context": "https://graph.microsoft.com/v1.0/$metadata#sites('XXXXX.sharepoint.com%2C495435b4-60c3-49b7-8f6e-1d262a120ae5%2C0fad9f67-35a8-4c0b-892e-113084058c0a')/lists('18a725ac-83ef-48fb-a5cb-950ca2378fd0')/items('10')/fields/$entity",
"fields": {
"#odata.etag": "\"13f60f9e-1bf2-4803-93b9-c45234963d47,3\"",
"SerialNumber": "20180824-1416-DC6-Generator-B",
"id": "10"
}
},
{
"#odata.etag": "\"00024848-0d4e-4ee8-b018-f1653af2a577,3\"",
"createdDateTime": "2018-08-25T22:47:30Z",
"eTag": "\"00024848-0d4e-4ee8-b018-f1653af2a577,3\"",
"id": "11",
"lastModifiedDateTime": "2018-08-25T22:47:30Z",
"webUrl": "https://XXXXX.sharepoint.com/sites/GeneratorApp/Lists/GenApp/11_.000",
"createdBy": {
"user": {
"email": "XXXXX#XXXXX.com",
"id": "b0465821-e891-4f44-9e18-27e875f1b75d",
"displayName": "XXXXX"
}
},
"lastModifiedBy": {
"user": {
"email": "XXXXX#XXXXX.com",
"id": "b0465821-e891-4f44-9e18-27e875f1b75d",
"displayName": "XXXXX"
}
},
"parentReference": {},
"contentType": {
"id": "0x0100E19591A4ECA81542AEA41A6AAFED6781"
},
"fields#odata.context": "https://graph.microsoft.com/v1.0/$metadata#sites('XXXXX.sharepoint.com%2C495435b4-60c3-49b7-8f6e-1d262a120ae5%2C0fad9f67-35a8-4c0b-892e-113084058c0a')/lists('18a725ac-83ef-48fb-a5cb-950ca2378fd0')/items('11')/fields/$entity",
"fields": {
"#odata.etag": "\"00024848-0d4e-4ee8-b018-f1653af2a577,3\"",
"SerialNumber": "20180824-1438-DC6-Generator-R",
"id": "11"
}
},
{
"#odata.etag": "\"7c8e80ed-6fea-408a-9594-2b7b13e3691b,3\"",
"createdDateTime": "2018-08-25T23:02:43Z",
"eTag": "\"7c8e80ed-6fea-408a-9594-2b7b13e3691b,3\"",
"id": "12",
"lastModifiedDateTime": "2018-08-25T23:02:43Z",
"webUrl": "https://XXXXX.sharepoint.com/sites/GeneratorApp/Lists/GenApp/12_.000",
"createdBy": {
"user": {
"email": "XXXXX#XXXXX.com",
"id": "b0465821-e891-4f44-9e18-27e875f1b75d",
"displayName": "XXXXX"
}
},
"lastModifiedBy": {
"user": {
"email": "XXXXX#XXXXX.com",
"id": "b0465821-e891-4f44-9e18-27e875f1b75d",
"displayName": "XXXXX"
}
},
"parentReference": {},
"contentType": {
"id": "0x0100E19591A4ECA81542AEA41A6AAFED6781"
},
"fields#odata.context": "https://graph.microsoft.com/v1.0/$metadata#sites('XXXXX.sharepoint.com%2C495435b4-60c3-49b7-8f6e-1d262a120ae5%2C0fad9f67-35a8-4c0b-892e-113084058c0a')/lists('18a725ac-83ef-48fb-a5cb-950ca2378fd0')/items('12')/fields/$entity",
"fields": {
"#odata.etag": "\"7c8e80ed-6fea-408a-9594-2b7b13e3691b,3\"",
"SerialNumber": "20180824-1456-DC6-Generator-C",
"id": "12"
}
}
]
}}
What I ultimately want to do is create a dropdown that is populated with the SerialNumber. When the SerialNumber is selected in the dropdown, it will return the id so that I can then plug that into a GET request to retrieve the appropriate listitems.
I am trying to figure out if I need to do a foreach to create a LIST<> or something else all together.
I do have this class setup, but wasn't sure if I could use it the way I thought I could.
public class Lookup
{
string id { get; set; };
string SerialNumber { get; set; }
}
This is the final working code:
private async void GetButton_Click(object sender, RoutedEventArgs e)
{
var (authResult, message) = await Authentication.AquireTokenAsync();
ResultText.Text = message;
if (authResult != null)
{
var httpClient = new HttpClient();
HttpResponseMessage response;
var request = new HttpRequestMessage(HttpMethod.Get, geturl);
//Add the token in Authorization header
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", authResult.AccessToken);
response = await httpClient.SendAsync(request);
var content = await response.Content.ReadAsStringAsync();
JObject json = JObject.Parse(content);
var result = JsonConvert.DeserializeObject<SharePointListItems.RootObject>(content);
foreach (var d in result.value)
{
Lookups.Add(new SharePointListItems.Lookup() { id = d.fields.id, SerialNumber = d.fields.SerialNumber });
}
TestComboBox.ItemsSource = Lookups;
}
}
private void TestComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (TestComboBox.SelectedIndex != -1)
{
var mylookupId = (TestComboBox.SelectedItem as SharePointListItems.Lookup).id;// get your id and do further processing here.
ResultText.Text = mylookupId;
}
}
public class SharePointListItems
{
public class Lookup
{
public string SerialNumber { get; set; }
public string id { get; set; }
public override string ToString()
{
return SerialNumber;
}
}
public class Value
{
public Lookup fields { get; set; }
}
public class Fields
{
[JsonProperty("#odata.etag")]
public string ODataETag { get; set; }
...
}
public class RootObject
{
[JsonProperty("#odata.context")]
public string ODataContext { get; set; }
[JsonProperty("#odata.etag")]
public string ODataETag { get; set; }
[JsonProperty("fields#odata.context")]
public string FieldsODataContext { get; set; }
public Fields Fields { get; set; }
public List<Value> value { get; set; }
}
}
There are two way can create model easily.
You can use Web Essentials in Visual Studio, use Edit > Paste special > paste JSON as class, you can easier to know the relation between Json and model.
If you can't use Web Essentials you can instead of use http://json2csharp.com/ online JSON to Model class.
You can try to use those models to carry your JSON Format.
public class Lookup
{
public string SerialNumber { get; set; }
public string id { get; set; }
}
public class Value
{
public Lookup fields { get; set; }
}
public class RootObject
{
public List<Value> value { get; set; }
}
Then you can use obj.value property collection directly.
var obj = JsonConvert.DeserializeObject<RootObject>(jsonData);
foreach (var item in obj.value)
{
//item.fields.id
//item.fields.SerialNumber
}
A good example of how to bind a list of data to Combobox ( dropdown ) is here : https://www.c-sharpcorner.com/article/data-binding-in-xaml-uwp-using-combobox/
in this example the class is a Student with id and Name and it shows how u can show the name in combobox.
I will modify it a little for your scenario but if you want to go in depth than you can visit the provided link above.
This is the class
public class Fields
{
public string SerialNumber { get; set; }
public string id { get; set; }
public override string ToString()
{
return this.SerialNumber; // so that we can just bind to the object and get serial number in the ui.
}
}
Backend for adding items to the List
public sealed partial class MainPage: Page
{
List<Lookup> Lookups = new List<Lookup>();
public MainPage()
{
this.InitializeComponent();
Lookups.Add(new Lookup() {id = 1, SerialNumber = "S1"});
Lookups.Add(new Lookup() {id = 2, SerialNumber = "S2"});
Lookups.Add(new Lookup() {id = 3, SerialNumber = "S3"});
Lookups.Add(new Lookup() {id = 4, SerialNumber = "S4"});
//add as many items here as u want, u can even use a for loop or foreach loop or a Deserializer with newsoft json to get objects from ur json like below.
//var data = JsonConvert.DeserializeObject<RootObject>(jsonData);
//foreach (var d in data.value)
//{
// //d.fields.id //this is how u can get the inside properties.
//}
yourComboBox.ItemSource = Lookups;//setting item source to UI.
}
}
after you successfully bind the data with UI you can use SelectionChanged event of your combobox to do further logic as you require,
void MyComboBox_SelectionChanged(object sender, object args)
{
if(MyCombobox.SelectedIndex!=-1)
{
var mylookupId = (MyCombobox.SelectedItem as Lookup).id;// get your id and do further processing here.
}
}
I think this will be easy when using newtonsoft:
var dynamicObject = JObject.Parse(yourstring);
var list = new List<Lookup>();
//now you have a dynamic object containing an array.
//this should be doable with linq as well.
//note, the type is dynamic
foreach (dynamic thing in dynamicObject )
{
list.Add(new Lookup()
{
id = thing.fields.id,
SerialNumber = thing.fields.SerialNumber
});
}
disclaimer: not tested in any way ;-)
I'm calling the ethplorer.io api, and it returns the below json. I have generated the classes in visual studio via 'paste special -> paste json as classes'. My problem is that Tokeninfo declares price as an object, this is because it can either be false if it has no price information, or a dictionary if it has values. While I have successfully deserialised the response using JsonConvert.DeserializeObject(rawJSON), I’m struggling to convert price in to c# dictionary if it has values.
public class Tokeninfo
{
public string address { get; set; }
public string name { get; set; }
public object decimals { get; set; }
public string symbol { get; set; }
public string totalSupply { get; set; }
public string owner { get; set; }
public long lastUpdated { get; set; }
public int issuancesCount { get; set; }
public int holdersCount { get; set; }
public object price { get; set; }
public string description { get; set; }
public float totalIn { get; set; }
public float totalOut { get; set; }
}
JSON response:
{
"address": "0xd8f41f341afe2c411b21b3f96263c6584b69baeb", //Not my address
"ETH": {
"balance": 762.13611095505,
"totalIn": 1040.0907032491,
"totalOut": 277.954592294
},
"countTxs": 22,
"tokens": [
{
"tokenInfo": {
"address": "0x355a458d555151d3b27f94227960ade1504e526a",
"name": "StockChain Coin",
"decimals": "18",
"symbol": "SCC",
"totalSupply": "10000000000000000000000000000",
"owner": "0x",
"lastUpdated": 1524401998,
"issuancesCount": 0,
"holdersCount": 86520,
"price": {
"rate": "0.0531126",
"diff": 4.8,
"diff7d": 19.82,
"ts": "1524400762",
"marketCapUsd": null,
"availableSupply": null,
"volume24h": "622004.0",
"currency": "USD"
}
},
"balance": 5000000000000000000,
"totalIn": 0,
"totalOut": 0
},
{
"tokenInfo": {
"address": "0xb679afd97bcbc7448c1b327795c3ef226b39f0e9",
"name": "Win Last Mile",
"decimals": "6",
"symbol": "WLM",
"totalSupply": "2000000000000000",
"owner": "0x8e7a75d5e7efe2981ac06a2c6d4ca8a987a44492",
"lastUpdated": 1524362946,
"issuancesCount": 0,
"holdersCount": 10945,
"price": false
},
"balance": 66000000,
"totalIn": 0,
"totalOut": 0
},
{
"tokenInfo": {
"address": "0xae66d00496aaa25418f829140bb259163c06986e",
"name": "Super Wallet Token",
"decimals": "8",
"symbol": "SW",
"totalSupply": "8400000000000000",
"owner": "0xba051682e9dbc40730fcef4a374e3a57a0ce3eff",
"lastUpdated": 1524401948,
"issuancesCount": 0,
"holdersCount": 30276,
"price": false
},
"balance": 11567900,
"totalIn": 0,
"totalOut": 0
},
{
"tokenInfo": {
"address": "0x8e4fbe2673e154fe9399166e03e18f87a5754420",
"name": "Universal Bonus Token | t.me/bubbletonebot",
"decimals": "18",
"symbol": "UBT",
"totalSupply": "1150000000000000000000000",
"owner": "0xc2db6e5b96dd22d9870a5ca0909cceac6604e21d",
"lastUpdated": 1524393745,
"issuancesCount": 0,
"holdersCount": 99896,
"price": false
},
"balance": 10000000000000000000,
"totalIn": 0,
"totalOut": 0
}
]
}
You need a custom deserializer to do what you want. It should be straight forward though. Here is some code which checks if the price is not false and then turns it into a Dictionary<string, string>. This code makes the assumption that your root object is named RootObject:
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var jsonObject = JObject.Load(reader);
var root = default(Rootobject);
// Let's go through each tokenInfo and check if price is not false
// so we can turn it into a dictionary.
foreach (var thisToken in root.tokens)
{
if (thisToken.tokenInfo.price.ToString() != "false")
{
thisToken.tokenInfo.price = JsonConvert.DeserializeObject<Dictionary<string, string>>(thisToken.tokenInfo.price.ToString());
}
}
serializer.Populate(jsonObject.CreateReader(), root);
return root;
}
Please see the full example here and search for ProfessionConverter in that link for the full class.
I think it is not very good approach to use false in cases when there is no price. If there is no price it should be something like "price" :{} or price element shouldn't be there at all. In other words, it is not good idea to mixup boolean object and dictionaty imho.
I think you can use provided by VisualStudio class where Price is an object. And you can create a custom serializer which will treat false as an null (or object with empty fields) along with standart deserialization mechanism.
"fields": [
{
"field": {
"name": "SMS",
"value": "Yes"
}
},
{
"field": {
"name": "Email",
"value": ""
}
},
{
"field": {
"name": "Total",
"value": ""
}
},
]
I have tried to form the JSON format like above, so i formed the class like below. While serialization it does not return expected form, how can i achieve this one.
public class Test
{
public List<Field> fields;
}
public class Field
{
public string name { get; set; }
public string value { get; set; }
}
Response:
"fields": [{
"name": "SMS",
"value": "Yes"
}, {
"name": "Email",
"value": ""
},{
"name": "Total",
"value": ""
}]
Use this website http://json2csharp.com and generate all the classes automatically. Just copy-paste your json there.
You can customize resulting JSON object with anonymous types and LINQ. Please try this code:
var test = new Test {fields = new List<Field>()};
test.fields.Add(new Field {name = "f1", value = "v1"});
test.fields.Add(new Field {name = "f2", value = "v2"});
var json = JObject.FromObject(new { fields = test.fields.Select(f => new {field = f}).ToArray() })
.ToString();
A json variable would be:
{
"fields": [
{
"field": {
"name": "f1",
"value": "v1"
}
},
{
"field": {
"name": "f2",
"value": "v2"
}
}
]
}
You just missed a class level:
public class Test
{
public List<FieldHolder> fields;
}
public class FieldHolder
{
public Field field { get; set; }
}
public class Field
{
public string name { get; set; }
public string value { get; set; }
}
I have an MVC application, that serializes my model into json schema (using Newtonsoft json.net schema). The problem is that items in my array have type ["string", "null"], but what I need is just "string". Here is code for my class:
public class Form
{
[Required()]
public string[] someStrings { get; set; }
}
This is schema made by Json.net schema:
"someStrings": {
"type": "array",
"items": {
"type": [
"string",
"null"
]
}
}
While I am expecting this:
"someStrings": {
"type": "array",
"items": {
"type": "string"
}
}
Help me get rid of that "null" please.
Try setting DefaultRequired to DisallowNull when you generate the schema:
JSchemaGenerator generator = new JSchemaGenerator()
{
DefaultRequired = Required.DisallowNull
};
JSchema schema = generator.Generate(typeof(Form));
schema.ToString();
Output:
{
"type": "object",
"properties": {
"someStrings": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
You can try this:
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
Try this ::
public class Employee
{
public string Name { get; set; }
public int Age { get; set; }
public decimal? Salary { get; set; }
}
Employee employee= new Employee
{
Name = "Heisenberg",
Age = 44
};
string jsonWithNullValues = JsonConvert.SerializeObject(person, Formatting.Indented);
output: with null
// {
// "Name": "Heisenberg",
// "Age": 44,
// "Salary": null
// }
string jsonWithOutNullValues = JsonConvert.SerializeObject(employee, Formatting.Indented, new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore
});
output: without null
// {
// "Name": "Heisenberg",
// "Age": 44
// }