Difficulty deserialising nested JSON - c#

I am calling a REST service to get back a JSON structure.
The error I get is
Test method BarPanda.Web.Services.Test.PosServiceTests.GetMenu threw exception:
System.MissingMethodException: No parameterless constructor defined for this object.
The original JSON is as follows (partial)
{
"count": 3,
"limit": 50,
"_links": {
"self": {
"etag": "b49a27c7e7c663af8d6a736e24fac7f5",
"href": "https://api.omnivore.io/0.1/locations/gcBdM7TL/menu/categories/" ,
"profile": "https://panel.omnivore.io/docs/api#category_list" 
}
},
"_embedded": {
"categories": [
{
"id": "AdiRjiAp",
"name": "Drinks",
"_links": {
"items": {
"etag": "05dad4d734401321a4854cf4f0369102",
"href": "https://api.omnivore.io/0.1/locations/gcBdM7TL/menu/categories/AdiRjiAp/items/" ,
"profile": "https://panel.omnivore.io/docs/api#menu-item_list" 
},
"self": {
"etag": "05dad4d734401321a4854cf4f0369102",
"href": "https://api.omnivore.io/0.1/locations/gcBdM7TL/menu/categories/AdiRjiAp/" ,
"profile": "https://panel.omnivore.io/docs/api#category_retrieve" 
}
},
"_embedded": {
"items": [
{
"id": "gki84ia9",
"in_stock": true,
"modifier_groups_count": 0,
"name": "Soda",
"open": false,
"pos_id": "gki84ia9",
"price": 150,
"price_levels": [
{
"id": "Byineidy",
"price": 150
},
{
"id": "g4T4dTBj",
"price": 200
},
{
"id": "K6czkc8b",
"price": 250
}
],
"_links": {
"modifier_groups": {
"href": "https://api.omnivore.io/0.1/locations/gcBdM7TL/menu/items/gki84ia9/modifier_groups/" ,
"profile": "https://panel.omnivore.io/docs/api#modifier-group_list" 
},
"self": {
"etag": "c59b380aed5c1f33915b028b739df955",
"href": "https://api.omnivore.io/0.1/locations/gcBdM7TL/menu/items/gki84ia9/" ,
"profile": "https://panel.omnivore.io/docs/api#menu-item_retrieve" 
}
}
},
{
"id": "doTaLTyg",
"in_stock": true,
"modifier_groups_count": 0,
"name": "Orange Juice",
"open": false,
"pos_id": "doTaLTyg",
"price": 175,
"price_levels": [
{
"id": "L4iqKid8",
"price": 175
},
{
"id": "K6T8MTzb",
"price": 300
}
],
"_links": {
"modifier_groups": {
"href": "https://api.omnivore.io/0.1/locations/gcBdM7TL/menu/items/doTaLTyg/modifier_groups/" ,
"profile": "https://panel.omnivore.io/docs/api#modifier-group_list" 
},
"self": {
"etag": "d3ae9754edb321f18e192ebea446baeb",
"href": "https://api.omnivore.io/0.1/locations/gcBdM7TL/menu/items/doTaLTyg/" ,
"profile": "https://panel.omnivore.io/docs/api#menu-item_retrieve" 
}
}
}
]
}
},
I am trying to deserialize it with the following code and object classes
var response = _client.Execute(request);
var converter = new JsonDeserializer();
var menu = converter.Deserialize<PosMenu>(response);
PosMenu
[DataContract]
public class PosMenu
{
[DataMember]
public int VenueId { get; set; }
[DataMember]
public int count { get; set; }
[DataMember]
public PosMenuEmbedded _embedded { get; set; }
}
PosMenuEmbedded
[DataContract]
public class PosMenuEmbedded
{
[DataMember]
public long UniqueId { get; set; }
[DataMember]
public PosMenuCategory[] categories { get; set; }
[DataMember]
public int PosMenuId { get; set; }
}
PosMenuCategory
[DataContract]
public class PosMenuCategory
{
}
Note: I have taken all properties out of this class for now just to see if I could get it working with a blank class, but alas not.
If I comment out the line in PosMenuEmbedded
public PosMenuCategory[] categories { get; set; }
It succeeds. If I put it back in, it fails, even with an empty class.
Can anyone suggest why this might be?

[DataMember]
public List<PosMenuCategory> categories { get; set; }

Related

Json.Net.Schema: How to generate a schema where only the [Required] properties are required?

I am writing a tool to work with resume.json files (project) and am creating a Json Schema to validate user input. I'm trying to automate this with Json.Net.Schema but the output always makes all properties required, regardless of whether the properties have the [Required] or [JsonRequired] attributes.
Schema Generation Code
var generator = new JSchemaGenerator
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
SchemaIdGenerationHandling = SchemaIdGenerationHandling.TypeName
};
var schema = generator.Generate(typeof(Resume));
var sb = new StringBuilder();
schema.WriteTo(new JsonTextWriter(
new IndentedTextWriter(
new StringWriter(sb),
" ")
)
{
Formatting = Formatting.Indented,
IndentChar = ' ', Indentation = 2,
QuoteName = true
}, new JSchemaWriterSettings
{
Version = SchemaVersion.Draft7
});
File.WriteAllText("E:\\resume.schema", sb.ToString());
Resume Class (and children)
public class Resume
{
[Required]
public Basics Basics { get; set; }
public Work[] Work { get; set; }
public Volunteer[] Volunteer { get; set; }
public Education[] Education { get; set; }
public Award[] Awards { get; set; }
public Publication[] Publications { get; set; }
public Skill[] Skills { get; set; }
public Language[] Languages { get; set; }
public Interest[] Interests { get; set; }
public Reference[] References { get; set; }
}
public class Award
{
[Required]
public string Title { get; set; }
public string Date { get; set; }
public string Awarder { get; set; }
public string Summary { get; set; }
}
public class Basics
{
[Required]
public string Name { get; set; }
public string Label { get; set; }
public Uri Picture { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public string Website { get; set; }
public string Summary { get; set; }
public Location Location { get; set; }
public Profile[] Profiles { get; set; }
}
public class Education
{
[Required]
public string Institution { get; set; }
public string Area { get; set; }
public string StudyType { get; set; }
public string StartDate { get; set; }
public string EndDate { get; set; }
public string Gpa { get; set; }
public string[] Courses { get; set; }
}
public class Interest
{
[Required]
public string Name { get; set; }
public string[] Keywords { get; set; }
}
public class Language
{
[Required]
public string language { get; set; }
[Required]
public string Fluency { get; set; }
}
public class Location
{
public string Address { get; set; }
[Required]
public string PostalCode { get; set; }
[Required]
public string City { get; set; }
[Required]
public string CountryCode { get; set; }
public string Region { get; set; }
}
public class Profile
{
[Required]
public string Network { get; set; }
[Required]
public string Username { get; set; }
[Required]
public string Url { get; set; }
}
public class Publication
{
[Required]
public string Name { get; set; }
public string Publisher { get; set; }
public string ReleaseDate { get; set; }
public string Website { get; set; }
public string Summary { get; set; }
}
public class Reference
{
[Required]
public string Name { get; set; }
public string reference { get; set; }
}
public class Skill
{
[Required]
public string Name { get; set; }
[Required]
public string Level { get; set; }
public string[] Keywords { get; set; }
}
public class Volunteer
{
[Required]
public string Organization { get; set; }
[Required]
public string Position { get; set; }
public string Website { get; set; }
public string StartDate { get; set; }
public string EndDate { get; set; }
public string Summary { get; set; }
public string[] Highlights { get; set; }
}
public class Work
{
[Required]
public string Company { get; set; }
[Required]
public string Position { get; set; }
public string Website { get; set; }
[Required]
public string StartDate { get; set; }
public string EndDate { get; set; }
public string Summary { get; set; }
public string[] Highlights { get; set; }
}
Current Output
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "Resume",
"definitions": {
"Award": {
"$id": "Award",
"type": [
"object",
"null"
],
"properties": {
"title": {
"type": "string"
},
"date": {
"type": [
"string",
"null"
]
},
"awarder": {
"type": [
"string",
"null"
]
},
"summary": {
"type": [
"string",
"null"
]
}
},
"required": [
"title",
"date",
"awarder",
"summary"
]
},
"Basics": {
"$id": "Basics",
"type": "object",
"properties": {
"name": {
"type": "string"
},
"label": {
"type": [
"string",
"null"
]
},
"picture": {
"type": [
"string",
"null"
],
"format": "uri"
},
"email": {
"type": [
"string",
"null"
]
},
"phone": {
"type": [
"string",
"null"
]
},
"website": {
"type": [
"string",
"null"
]
},
"summary": {
"type": [
"string",
"null"
]
},
"location": {
"$id": "Location",
"type": [
"object",
"null"
],
"properties": {
"address": {
"type": [
"string",
"null"
]
},
"postalCode": {
"type": "string"
},
"city": {
"type": "string"
},
"countryCode": {
"type": "string"
},
"region": {
"type": [
"string",
"null"
]
}
},
"required": [
"address",
"postalCode",
"city",
"countryCode",
"region"
]
},
"profiles": {
"$id": "Profile[]",
"type": [
"array",
"null"
],
"items": {
"$id": "Profile",
"type": [
"object",
"null"
],
"properties": {
"network": {
"type": "string"
},
"username": {
"type": "string"
},
"url": {
"type": "string"
}
},
"required": [
"network",
"username",
"url"
]
}
}
},
"required": [
"name",
"label",
"picture",
"email",
"phone",
"website",
"summary",
"location",
"profiles"
]
},
"Education": {
"$id": "Education",
"type": [
"object",
"null"
],
"properties": {
"institution": {
"type": "string"
},
"area": {
"type": [
"string",
"null"
]
},
"studyType": {
"type": [
"string",
"null"
]
},
"startDate": {
"type": [
"string",
"null"
]
},
"endDate": {
"type": [
"string",
"null"
]
},
"gpa": {
"type": [
"string",
"null"
]
},
"courses": {
"$id": "String[]",
"type": [
"array",
"null"
],
"items": {
"type": [
"string",
"null"
]
}
}
},
"required": [
"institution",
"area",
"studyType",
"startDate",
"endDate",
"gpa",
"courses"
]
},
"Interest": {
"$id": "Interest",
"type": [
"object",
"null"
],
"properties": {
"name": {
"type": "string"
},
"keywords": {
"$id": "String[]",
"type": [
"array",
"null"
],
"items": {
"type": [
"string",
"null"
]
}
}
},
"required": [
"name",
"keywords"
]
},
"Language": {
"$id": "Language",
"type": [
"object",
"null"
],
"properties": {
"language": {
"type": "string"
},
"fluency": {
"type": "string"
}
},
"required": [
"language",
"fluency"
]
},
"Location": {
"$ref": "Location"
},
"Profile": {
"$ref": "Profile"
},
"Publication": {
"$id": "Publication",
"type": [
"object",
"null"
],
"properties": {
"name": {
"type": "string"
},
"publisher": {
"type": [
"string",
"null"
]
},
"releaseDate": {
"type": [
"string",
"null"
]
},
"website": {
"type": [
"string",
"null"
]
},
"summary": {
"type": [
"string",
"null"
]
}
},
"required": [
"name",
"publisher",
"releaseDate",
"website",
"summary"
]
},
"Reference": {
"$id": "Reference",
"type": [
"object",
"null"
],
"properties": {
"name": {
"type": "string"
},
"reference": {
"type": [
"string",
"null"
]
}
},
"required": [
"name",
"reference"
]
},
"Skill": {
"$id": "Skill",
"type": [
"object",
"null"
],
"properties": {
"name": {
"type": "string"
},
"level": {
"type": "string"
},
"keywords": {
"$id": "String[]",
"type": [
"array",
"null"
],
"items": {
"type": [
"string",
"null"
]
}
}
},
"required": [
"name",
"level",
"keywords"
]
},
"Volunteer": {
"$id": "Volunteer",
"type": [
"object",
"null"
],
"properties": {
"organization": {
"type": "string"
},
"position": {
"type": "string"
},
"website": {
"type": [
"string",
"null"
]
},
"startDate": {
"type": [
"string",
"null"
]
},
"endDate": {
"type": [
"string",
"null"
]
},
"summary": {
"type": [
"string",
"null"
]
},
"highlights": {
"$id": "String[]",
"type": [
"array",
"null"
],
"items": {
"type": [
"string",
"null"
]
}
}
},
"required": [
"organization",
"position",
"website",
"startDate",
"endDate",
"summary",
"highlights"
]
},
"Work": {
"$id": "Work",
"type": [
"object",
"null"
],
"properties": {
"company": {
"type": "string"
},
"position": {
"type": "string"
},
"website": {
"type": [
"string",
"null"
]
},
"startDate": {
"type": "string"
},
"endDate": {
"type": [
"string",
"null"
]
},
"summary": {
"type": [
"string",
"null"
]
},
"highlights": {
"$id": "String[]",
"type": [
"array",
"null"
],
"items": {
"type": [
"string",
"null"
]
}
}
},
"required": [
"company",
"position",
"website",
"startDate",
"endDate",
"summary",
"highlights"
]
}
},
"type": "object",
"properties": {
"basics": {
"$ref": "Basics"
},
"work": {
"$id": "Work[]",
"type": [
"array",
"null"
],
"items": {
"$ref": "Work"
}
},
"volunteer": {
"$id": "Volunteer[]",
"type": [
"array",
"null"
],
"items": {
"$ref": "Volunteer"
}
},
"education": {
"$id": "Education[]",
"type": [
"array",
"null"
],
"items": {
"$ref": "Education"
}
},
"awards": {
"$id": "Award[]",
"type": [
"array",
"null"
],
"items": {
"$ref": "Award"
}
},
"publications": {
"$id": "Publication[]",
"type": [
"array",
"null"
],
"items": {
"$ref": "Publication"
}
},
"skills": {
"$id": "Skill[]",
"type": [
"array",
"null"
],
"items": {
"$ref": "Skill"
}
},
"languages": {
"$id": "Language[]",
"type": [
"array",
"null"
],
"items": {
"$ref": "Language"
}
},
"interests": {
"$id": "Interest[]",
"type": [
"array",
"null"
],
"items": {
"$ref": "Interest"
}
},
"references": {
"$id": "Reference[]",
"type": [
"array",
"null"
],
"items": {
"$ref": "Reference"
}
}
},
"required": [
"basics",
"work",
"volunteer",
"education",
"awards",
"publications",
"skills",
"languages",
"interests",
"references"
]
}
How do I get the schema generator to honor the Required attributes?
JSchemaGenerator has a property DefaultRequired:
Gets or sets the default required state of schemas.
For some reason, the default value for this property is Required.AllowNull, as shown in the source:
public JSchemaGenerator()
{
_schemaReferenceHandling = SchemaReferenceHandling.Objects;
_defaultRequired = Required.AllowNull;
}
If you change it to Required.Default, only those properties explicitly marked as required, e.g. with [Required] or [JsonProperty(Required = Required.Always)], will be listed as required in the schema:
var generator = new JSchemaGenerator
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
SchemaIdGenerationHandling = SchemaIdGenerationHandling.TypeName,
DefaultRequired = Required.Default,
};
The default value for DefaultRequired isn't documented, but probably should be. You might open an issue with Newtonsoft requesting a clarification to the documentation.
Demo fiddle here.

Validation of an invalid json data with Schema not failing with Deserialization

I am parsing the following JSON:
{"names":{"organizationNames":[{"name":"apple"}]}}
into the schema defined in C# Code as shown below.
public class QueryJson
{
#region Properties
[JsonProperty("organization")]
public HeOrganization Organization { get; set; }
[JsonProperty("names")]
public HeName Names { get; set; }
[JsonProperty("emails")]
public List<HeEmailAddress> Emails { get; set; }
#endregion
#region Linked Classes
public class HeOrganization
{
[JsonProperty("id")]
public Guid? ID { get; set; }
}
public class HeName
{
[JsonProperty("organizationNames")]
[Required(ErrorMessage = "Organization Name is Missing")]
public List<HeOrganizationName> OrganizationName { get; set; }
public class HeOrganizationName
{
[JsonProperty("name")]
[Required(ErrorMessage = "Name is Missing")]
public string Name { get; set; }
}
}
public class HeEmailAddress
{
[JsonProperty("address")]
[Required]
[EmailAddress]
public string Address { get; set; }
}
#endregion
}
If I were to pass an obviously invalid JSON:
{"names":{"organizationNames":[{"user":"apple"}]}}
I was expecting DeserializeObject() to fail or throw an Error, but instead it simply assigns 'Name' to null.
var myJson = JsonConvert.DeserializeObject<T>(jsonFilter);
Where T is the instance of the class.
Any suggestion on how to perform such Validations?
You could use Newtonsoft.Json.Schema to validate the schema of any given Json.
For example, for the class structure you have defined, an equivalent Schema could be generated as
var generator = new JSchemaGenerator();
var schema = generator.Generate(typeof(QueryJson));
The Generated Schema is as follows
{
"definitions": {
"HeEmailAddress": {
"type": [
"object",
"null"
],
"properties": {
"address": {
"type": "string",
"format": "email"
}
},
"required": [
"address"
]
},
"HeName": {
"type": [
"object",
"null"
],
"properties": {
"organizationNames": {
"type": "array",
"items": {
"$ref": "#/definitions/HeOrganizationName"
}
}
},
"required": [
"organizationNames"
]
},
"HeOrganization": {
"type": [
"object",
"null"
],
"properties": {
"id": {
"type": [
"string",
"null"
]
}
},
"required": [
"id"
]
},
"HeOrganizationName": {
"type": [
"object",
"null"
],
"properties": {
"name": {
"type": "string"
}
},
"required": [
"name"
]
}
},
"type": "object",
"properties": {
"organization": {
"$ref": "#/definitions/HeOrganization"
},
"names": {
"$ref": "#/definitions/HeName"
},
"emails": {
"type": [
"array",
"null"
],
"items": {
"$ref": "#/definitions/HeEmailAddress"
}
}
},
"required": [
"organization",
"names",
"emails"
]
}
You could now use the Schema to validate your jsons. For example, for the sample invalid json provided in OP
var invalidJson = #"{""names"":{""organizationNames"":[{""user"":""apple""}]}}";
var jsonInstance = JObject.Parse(invalidJson);
bool valid = jsonInstance.IsValid(schema); // False

Deserialize json data c#

I want to deserialize JSON response received by Telegram Bot API by getUpdate() method.
JSON data:
{
"ok": true,
"result": [
{
"update_id": 920493886,
"message": {
"message_id": 123,
"from": {
"id": 219633031,
"first_name": "Shreeeeeee",
"username": "Winner7777"
},
"chat": {
"id": 219633031,
"first_name": "Shreeeeeee",
"username": "Winner7777",
"type": "private"
},
"date": 1472457375,
"text": "Aata aala"
}
},
{
"update_id": 920493887,
"message": {
"message_id": 124,
"from": {
"id": 219633031,
"first_name": "Shreeeeeee",
"username": "Winner7777"
},
"chat": {
"id": 219633031,
"first_name": "Shreeeeeee",
"username": "Winner7777",
"type": "private"
},
"date": 1472457387,
"text": "Jeva tuzyakadun reply aala tevha"
}
},
{
"update_id": 920493888,
"message": {
"message_id": 125,
"from": {
"id": 219633031,
"first_name": "Shreeeeeee",
"username": "Winner7777"
},
"chat": {
"id": 219633031,
"first_name": "Shreeeeeee",
"username": "Winner7777",
"type": "private"
},
"date": 1472457443,
"text": "Deposite"
}
},
{
"update_id": 920493889,
"message": {
"message_id": 127,
"from": {
"id": 201520743,
"first_name": "Chandrakant",
"last_name": "Kumathekar",
"username": "chandrakant_k"
},
"chat": {
"id": 201520743,
"first_name": "Chandrakant",
"last_name": "Kumathekar",
"username": "chandrakant_k",
"type": "private"
},
"date": 1472457645,
"text": "\/menu",
"entities": [
{
"type": "bot_command",
"offset": 0,
"length": 5
}
]
}
},
{
"update_id": 920493890,
"message": {
"message_id": 128,
"from": {
"id": 219633031,
"first_name": "Shreeeeeee",
"username": "Winner7777"
},
"chat": {
"id": 219633031,
"first_name": "Shreeeeeee",
"username": "Winner7777",
"type": "private"
},
"date": 1472457670,
"text": "\/menu",
"entities": [
{
"type": "bot_command",
"offset": 0,
"length": 5
}
]
}
},
{
"update_id": 920493891,
"message": {
"message_id": 130,
"from": {
"id": 201520743,
"first_name": "Chandrakant",
"last_name": "Kumathekar",
"username": "chandrakant_k"
},
"chat": {
"id": 201520743,
"first_name": "Chandrakant",
"last_name": "Kumathekar",
"username": "chandrakant_k",
"type": "private"
},
"date": 1472457848,
"text": "Deposite"
}
},
{
"update_id": 920493892,
"message": {
"message_id": 132,
"from": {
"id": 201520743,
"first_name": "Chandrakant",
"last_name": "Kumathekar",
"username": "chandrakant_k"
},
"chat": {
"id": 201520743,
"first_name": "Chandrakant",
"last_name": "Kumathekar",
"username": "chandrakant_k",
"type": "private"
},
"date": 1472457883,
"text": "Deposite"
}
},
{
"update_id": 920493893,
"message": {
"message_id": 133,
"from": {
"id": 219633031,
"first_name": "Shreeeeeee",
"username": "Winner7777"
},
"chat": {
"id": 219633031,
"first_name": "Shreeeeeee",
"username": "Winner7777",
"type": "private"
},
"date": 1472468407,
"text": "\/menu",
"entities": [
{
"type": "bot_command",
"offset": 0,
"length": 5
}
]
}
},
{
"update_id": 920493894,
"message": {
"message_id": 134,
"from": {
"id": 219633031,
"first_name": "Shreeeeeee",
"username": "Winner7777"
},
"chat": {
"id": 219633031,
"first_name": "Shreeeeeee",
"username": "Winner7777",
"type": "private"
},
"date": 1472473070,
"text": "\/menu",
"entities": [
{
"type": "bot_command",
"offset": 0,
"length": 5
}
]
}
}
]
}
I have generated classes from json2csharp
public class From
{
public int id { get; set; }
public string first_name { get; set; }
public string last_name { get; set; }
public string username { get; set; }
}
public class Chat
{
public int id { get; set; }
public string first_name { get; set; }
public string last_name { get; set; }
public string type { get; set; }
public string username { get; set; }
}
public class Entity
{
public string type { get; set; }
public int offset { get; set; }
public int length { get; set; }
}
public class Message
{
public int message_id { get; set; }
public From from { get; set; }
public Chat chat { get; set; }
public int date { get; set; }
public string text { get; set; }
public List<Entity> entities { get; set; }
}
public class Result
{
public int update_id { get; set; }
public Message message { get; set; }
}
public class RootObject
{
public bool ok { get; set; }
public List<Result> result { get; set; }
}
using newtonsoft to deserialization
var d = Newtonsoft.Json.JsonConvert.DeserializeObject(rcvd_data);
what to do next? how to put this all at work? I am confused please help.
To deserialization use this code:
RootObject ro = JsonConvert.DeserializeObject<RootObject>(rcvd_data);
And in ro you have all data.
EXAMPLE
bool ok = ro.ok;
foreach(Result r in ro.result)
{
int uId = r.update_id;
Message m = r.message;
int msgId = m.message_id;
}
string data = #"{""ok"":true,""result"":[{""update_id"":920493886,...";
RootObject ro = Newtonsoft.Json.JsonConvert.DeserializeObject<RootObject>(data);
foreach (Result result in ro.result)
{
//two example fields
Console.WriteLine("update_id= " + result.update_id);
Console.WriteLine("message text= "+result.message.text);
}
Based on: https://yts.am/api/v2/list_movies.json (Source: https://yts.am/api)
I used: http://json2csharp.com/ to create classes
Copy and paste the result of the get request of postman to json2csharp to automatically create the classes that you need
And once created, i used them on a Service like this:
private string URL = "https://yts.am/api/v2/list_movies.json";
public async Task<List<Movie>> GetMovies()
{
var httpClient = new HttpClient();
var json = await httpClient.GetStringAsync(URL);
RootObject lista = Newtonsoft.Json.JsonConvert.DeserializeObject<RootObject>(json);
List<Movie> todoes = lista.data.movies;
return todoes;
}
I'm using Newtonsoft.Json
Try this way
var d = Newtonsoft.Json.JsonConvert.DeserializeObject<RootObject>(rcvd_‌​data);
then d will contain list of RootObject. By iterating using foreach you can get all the properties of RootObject model

Web Api; Entity Framework; Data returns recursive

im facing a problem with probably selfreference Looping:
Model:
public class ProtectedAccount
{
public int Id { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime Created { get; private set; }
public DateTime? Changed { get; set; }
public bool Disabled { get; set; }
public virtual ICollection<ProtectedAccountMember> Members { get; set; }
public virtual ProtectedAccountType Type { get; set; }
}
public class ProtectedAccountMember
{
public int Id { get; set; }
[StringLength(300)]
public string Name { get; set; }
[Index]
public virtual ProtectedAccount ProtectedAccount { get; set; }
}
Controller:
[ResponseType(typeof(ProtectedAccount))]
[Route("ProtectedAccounts/{id}/Members")]
[HttpGet]
public IHttpActionResult GetProtectedAccountMembers(int id)
{
var protectedAccount = db.ProtectedAccounts.Find(id);
if (protectedAccount == null)
{
return NotFound();
}
return Ok(protectedAccount.Members.ToList());
}
the data wich i receive for an GET seems to Loop recursive through all navigations:
[
{
"ProtectedAccount": {
"Members": [
{
"Id": 2,
"Name": "XXX, XX",
},
{
"Id": 3,
"Name": "XX, XX",
}
],
"Type": null,
"Id": 25,
"ObjectGUID": "76bf65e7-af60-4fe8-b3e1-90afbfd65b65",
"Name": "XXX",
},
"Id": 1,
"Name": "test",
},
{
"ProtectedAccount": {
"Members": [
{
"Id": 1,
"Name": "test",
},
{
"Id": 3,
"Name": "XX, XX",
"SamAccountName": "XX",
"Disabled": false
}
],
"Type": null,
"Id": 25,
"ObjectGUID": "76bf65e7-af60-4fe8-b3e1-90afbfd65b65",
"Name": "XXXX",
},
"Id": 2,
"Name": "XX, XX",
},
{
"ProtectedAccount": {a
"Members": [
{
"Id": 1,
"Name": "test",
"SamAccountName": "XXX",
"Disabled": false
},
{
"Id": 2,
"Name": "XX, XX",
"SamAccountName": "XX",
"Disabled": false
}
],
"Type": null,
"Id": 25,
"ObjectGUID": "76bf65e7-af60-4fe8-b3e1-90afbfd65b65",
"Name": "XXX",
},
"Id": 3,
"Name": "XX, XX",
}
]
There is only one "ProtectedAccount" in the database. DO i have to use DTO to overcome this issue? I tried some configuration via the json formatsettings but didnt get any better results.
From your code, you are only returing the protectedAccount.Members, hence you could do a projection query as below
var results = ctx.ProtectedAccountMembers
.Where(member => member.ProtectedAccount.Id == protectedAccount.Id)
.Select(member => new { member.Id, member.Name }).ToList();

SerializationException: End element 'caption' from namespace '' expected

I'm trying to deserialize a json string and I'm getting the error End element 'caption' from namespace '' expected. Found element 'created_time' from namespace ''. when calling
InstagramObject test = (InstagramObject) instagramObject.ReadObject(instagramWebResponse.GetResponseStream());
The json from Instagram returns many elements but there are only a few that I need. My DataContract will be posted below.
Basically I need {data:[{caption: string, link: string, images: {...}}]}
Here's an example of the json...
{
"data": [{
"comments": {
"data": [],
"count": 0
},
"caption": {
"created_time": "1296710352",
"text": "Inside le truc #foodtruck",
"from": {
"username": "kevin",
"full_name": "Kevin Systrom",
"type": "user",
"id": "3"
},
"id": "26621408"
},
"likes": {
"count": 15,
"data": [{
"username": "mikeyk",
"full_name": "Mike Krieger",
"id": "4",
"profile_picture": "..."
}, {...subset of likers...}]
},
"link": "http://instagr.am/p/BWrVZ/",
"user": {
"username": "kevin",
"profile_picture": "http://distillery.s3.amazonaws.com/profiles/profile_3_75sq_1295574122.jpg",
"id": "3"
},
"created_time": "1296710327",
"images": {
"low_resolution": {
"url": "http://distillery.s3.amazonaws.com/media/2011/02/02/6ea7baea55774c5e81e7e3e1f6e791a7_6.jpg",
"width": 306,
"height": 306
},
"thumbnail": {
"url": "http://distillery.s3.amazonaws.com/media/2011/02/02/6ea7baea55774c5e81e7e3e1f6e791a7_5.jpg",
"width": 150,
"height": 150
},
"standard_resolution": {
"url": "http://distillery.s3.amazonaws.com/media/2011/02/02/6ea7baea55774c5e81e7e3e1f6e791a7_7.jpg",
"width": 612,
"height": 612
}
},
"type": "image",
"filter": "Earlybird",
"tags": ["foodtruck"],
"id": "22721881",
"location": {
"latitude": 37.778720183610183,
"longitude": -122.3962783813477,
"id": "520640",
"street_address": "",
"name": "Le Truc"
}
}]
}
and here's my DataContract...
[DataContract]
public class InstagramObject {
[DataMember(Name = "data")]
public IEnumerable<InstagramData> instagramData { get; set; }
}
[DataContract]
public class InstagramData {
[DataMember(Name = "images")]
public List<InstagramImage> instagramImages { get; set; }
[DataMember(Name = "caption")]
public string caption { get; set; }
[DataMember(Name = "link")]
public string link { get; set; }
}
[DataContract]
public class InstagramImage {
[DataMember(Name = "low_resolution")]
public InstagramImageInfo lowResolutionImage { get; set; }
[DataMember(Name = "thumbnail")]
public InstagramImageInfo thumbnail { get; set; }
[DataMember(Name = "standard_resolution")]
public InstagramImageInfo standardResolution { get; set; }
}
[DataContract]
public class InstagramImageInfo {
[DataMember(Name = "url")]
public string url { get; set; }
[DataMember(Name = "width")]
public int width { get; set; }
[DataMember(Name = "height")]
public int height { get; set; }
}
In the data contract caption is declared as a string, but in the JSON caption is a record with various fields - caption should be declared to be an object with a compatible structure:
[DataContract]
public class InstagramCaption {
[DataMember(Name = "text")]
public string Text {get; set;}
}
. . .
[DataMember(Name = "caption")]
public InstagramCaption caption { get; set; }
. . .
No need to declare those clases If you want to go with Json.Net + Linq
var obj = (JObject)JsonConvert.DeserializeObject(json);
var result = obj["data"]
.Select(x => new {
Caption = (string)x["caption"]["text"],
Link = (string)x["link"],
Images = x["images"].Children()
.Select(y=>(string)y.First()["url"]).ToArray()
})
.ToArray();

Categories