List<Object> serialization not working with multiple objects - json

I have the following classes
[DataContract]
public class Video
{
[Key]
[DataMember(IsRequired = false)]
public int VideoId { get; set; }
[DataMember(IsRequired = false)]
public int UserId { get; set; }
[Required]
[DataMember ]
public string Title { get; set; }
[Required]
[DataMember]
public virtual IList<Tag> Tags { get; set; }
}
[DataContract]
public class Tag
{
[Key]
[Required]
[DataMember(IsRequired = false)]
public int? TagId { get; set; }
[DataMember(IsRequired = true)]
[Required]
public string Name { get; set; }
[IgnoreDataMember]
public virtual IList<Video> Videos { get; set; }
}
In my WebAPI controller, I call this:
var videos = _service.GetVideos();
return Request.CreateResponse(HttpStatusCode.OK, videos);
Which calls this:
public IList<Video> GetVideos()
{
using (var db = CreateContext())
{
return db.Videos.Include("Tags").ToList();
}
}
Yet over the wire, this is what I get:
[{
"$id": "8",
"tags": [
{
// CORRECT SERIALIZATION
"$id": "9",
"tagId": 1,
"name": "Example",
"count": 5
}
],
"videoId": 18,
"userId": 3,
"title": "Test Video",
"thumbnail": "http://i.imgur.com/gV3J2Uf.png",
"source": "test source"
},
{
"$id": "19",
"tags": [
{
// WTF?
"$ref": "9"
}
],
"videoId": 28,
"userId": 6,
"title": "Test Video",
"thumbnail": "http://i.imgur.com/gV3J2Uf.png",
"source": "test source"
},
{
"$id": "20",
"tags": [
{
// CORRECT AGAIN
"$id": "21",
"tagId": 10,
"name": "funny",
"count": 2
}
],
"videoId": 29,
"userId": 6,
"title": "TEST VID",
"thumbnail": "https://i.imgur.com/SWOQSOf.jpg",
"source": "test source"
},
{
"$id": "22",
"tags": [
{
// INCORRECT
"$ref": "9"
},
{
"$ref": "21"
}
],
"videoId": 30,
"userId": 6,
"title": "TEST VID",
"thumbnail": "https://i.imgur.com/R7lVobX.jpg",
"source": "test source"
}
For some reason - tags is sometimes serializing correctly, and sometimes not. Any idea what I'm doing wrong?

You have circular references in your object graph. They cannot be JSON serialized properly, the serializer detects this condition and automatically makes references ($ref). when you are loading the object graph using EF there are circular references between those objects in memory which cannot be represented correctly in JSON.
I would recommend you breaking the circular references graph by using a view model and then sending the view model over the wire instead of directly returning your autogenerated EF models.

Related

Getting Newtonsoft.Json.JsonSerializationException error when deserializing a Json object

I'm having an issue when trying to send Docusign envelope with custom recipient mail (using recipientMailNotification) trough its API service. My controller receives the request properly, but before it sends to docusign service it deserializes into an object, and that's when the error occurs.
**JSON Request:**
"Recipients": [{
"Order": 1,
"Name": "Andre Test ",
"Email": "andre#test.com",
"SignerType": "SIGNER",
"DocusignSignerType": 0,
"SignatureType": "ELECTRONIC",
"EtapaFinalizada": false,
"EmailNotification":{
"emailBody": "SIGN AS SIGNER",
"emailSubject": "SIGNER SIGNATURE REQUIRED"
}
},
{
"Order": 2,
"Name": "Luis Teste",
"Email": "luis#test.com",
"SignerType": "WITNESS",
"DocusignSignerType": 0,
"SignatureType": "ELECTRONIC",
"EtapaFinalizada": false,
"EmailNotification": {
"emailBody": "SIGN AS WITNESS",
"emailSubject": "WITNESS SIGNATURE REQUIRED"
}
}
]
Gives me the error:
'Cannot deserialize the current JSON object
(e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[eSignature.
Providers.Docusign.Entities.RecipientEmailNotification]'
I'm not using a list<> or array of any type. is just a standard property nested inside another.
Tried the solution listed here but still getting the error.
Using Json2CSharp gives me same structure as my current class so I assume it is correct Json.
EDIT: Please note that I'm not even expeting an array or List on my class property:
public class Destinatario
{
public int Order { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string SignerType{ get; set; }
public int DocusignSignerType{ get; set; }
public string SignatureType{ get; set; }
public bool EtapaFinalizada { get; set; }
public RecipientEmailNotification EmailNotification { get; set; }
}
Recipients JSON looks like this:
"recipients": {
"signers": [{
"email": "test1#email.com",
"name": "Name 1",
"recipientId": "1",
"routingOrder": "1",
"tabs": {
"signHereTabs": *[{
"xPosition": "100",
"yPosition": "100",
"documentId": "1",
"pageNumber": "1"
}]
}
},
{
"email": "test2#email.com",
"name": "Name 2",
"recipientId": "2",
"routingOrder": "2",
"tabs": {
"initialHereTabs": *[{
"xPosition": "100",
"yPosition": "200",
"documentId": "1",
"pageNumber": "1"
}],
"signHereTabs": [*{
"xPosition": "200",
"yPosition": "200",
"documentId": "1",
"pageNumber": "1"
}]
}
}
],
"carbonCopies": [{
"email": "test3#email.com",
"name": "Name 3",
"recipientId": "3",
"routingOrder": "3"
},
{
"email": "test*4#email.com",
"name": "Name 4",
"recipientId": "4",
"routingOrder": "3"
}
]
}
You do not have it separated into different kinds of recipients so your JSON is invalid.
Please see https://developers.docusign.com/esign-rest-api/guides/features/recipients for more information.

How to store GeoJSON in PostgreSQL

I'm trying to get a JSON formatted like GeoJSON with API. I get something for GET and can DELETE but when i try to post or put i get this error System.NotSupportedException: Deserialization of reference types without parameterless constructor is not supported. Type 'System.Text.Json.JsonDocument'
Also I'm not getting exactly what I have in PostgreSQL. There is an extra "rootElement"
In PostgreSQL I have a table with columns ID(integer),type(string),properties(json),geometry(json).
I insert this
{
"id": 1,
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [23.2,23]
},
"properties": {
"name": "test2",
"type": "testing"
}
}
And this is my class
public class Test
{
public long ID { get; set; }
public string type { get; set; }
public System.Text.Json.JsonDocument geometry { get; set; }
public System.Text.Json.JsonDocument properties { get; set; }
}
What I get with GET is this
[
{
"id": 2,
"type": "test",
"geometry": {
"rootElement": {
"type": "point",
"coordinates": [
23.2,
23
]
}
},
"properties": {
"rootElement": {
"name": "test2",
"type": "testing"
}
}
}
]

JSON request to ASP.NET API

I have the following JSON Data:
{
"0": {
"id": 0,
"type": "camera",
"option": [
{
"optionId": 1,
"optionValue": "",
"answered": "false",
"lastanswerd": "false"
}
]
},
"1": {
"id": 1,
"type": "checkCategory",
"option": [
{
"optionId": 1,
"optionValue": "",
"answered": "false",
"lastanswerd": "false"
},
{
"optionId": 2,
"optionValue": "",
"answered": "false",
"lastanswerd": "false"
}
]
}
}
How to pass JSON data into ASP.NET API request with which type of parameter in controller action?
Asp.net MVC automap and try to cast each key:value of json.
{"key1":"value", "key2":"value"}
You can access those values using params inside your function
public ActionResult Index(string key,string key2)
Or creating a class with public setter equal to your keys and a parameterless constructor.
public Class MyJson
{
public string key1 {get;set;}
public string key2 {get;set;}
}
public ActionResult Index(MyJson model)
In your specific case your passing a List of Object so you should use
public ActionResult Index(List<MyJson> model)
If you change your json to:
[
{
"id": 0,
"type": "camera",
"option": [
{
"optionId": 1,
"optionValue": "",
"answered": "false",
"lastanswerd": "false"
}
]
},
{
"id": 1,
"type": "checkCategory",
"option": [
{
"optionId": 1,
"optionValue": "",
"answered": "false",
"lastanswerd": "false"
},
{
"optionId": 2,
"optionValue": "",
"answered": "false",
"lastanswerd": "false"
}
]
}
]
json2csharp gives us:
public class Option
{
public int optionId { get; set; }
public string optionValue { get; set; }
public string answered { get; set; }
public string lastanswerd { get; set; }
}
public class RootObject
{
public int id { get; set; }
public string type { get; set; }
public List<Option> option { get; set; }
}

How do I LINQ multi-nested lists to JSON in MVC Web Api?

I'd like to learn to do this, because it gives me headaches :S
Goal:
To make as few DB queries to get a logical JSON object for my app.
Scenario
An app for a school where parents can pay for activities for their children.
A parent has many students, a student has many line-items (orders), a line-item works as a join-table between student and product.
Models:
public class Parent
{
public int ParentId { get; set; }
public string FullName { get; set; }
public virtual ICollection<Student> Students { get; set; }
}
public class Student
{
public int StudentId { get; set; }
public string FullName { get; set; }
public int ParentId { get; set; }
public virtual Parent Parent { get; set; }
public virtual ICollection<LineItem> LineItems { get; set; }
}
public class Product
{
public int ProductId { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public virtual ICollection<LineItem> LineItems { get; set; }
}
public class LineItem
{
public int Id { get; set; }
public int ProductId { get; set; }
public int StudentId { get; set; }
public int Discount {get; set;}
// ...
public virtual Product Product { get; set; }
public virtual Student Student { get; set; }
}
JSON I'd like to generate:
{
"Parent": {
"ParentId": 10,
"FullName": "John Doe",
"Students": [
{
"StudentId": 12,
"FullName": "William Doe",
"ParentId": 10,
"LineItems": [
{
"Discount": 10,
"Price": 150,
"Name": "Student trip to Washington"
},
{
"Discount": 10,
"Price": 20,
"Name": "Halloween party"
}
]
},
{
"StudentId": 15,
"FullName": "Kate Mary-Jane Doe",
"ParentId": 10,
"LineItems": [
{
"Discount": 10,
"Price": 110,
"Name": "Spring Break to Mexico"
}
]
}
]
}
}
Notes:
I have experimented with View Models and AutoMapper, but I can't get the nested output of everything. The best I could do was get a nested Parent -> Students[] output, but could not figure out how to get to the LineItems and Products.
Following solution may be help you
I am using Nortwnd Sample database, with 3 tables, Customers,Orders,OrdersDetails , As you know relation bewteen these tables Customer has many orders has many products
Following is working example
using System.Web.Script.Serialization;
var json = new List();
foreach (var c in customers)
{
json.Add(new
{
c.CustomerID,
custname =c.CompanyName,
Orders = c.Orders.Select(o => new
{
o.OrderID,
o.OrderDate,
OrderDetails=o.Order_Details.Select(d=> new{
d.OrderID,
d.ProductID
})
})
});
}
var serializer = new JavaScriptSerializer();
var jsonString = serializer.Serialize(json);
Response.Write(jsonString.ToString());
OUTPUT
[
{
"CustomerID": "WOLZA",
"custname": "Wolski Zajazd",
"Orders": [
{
"OrderID": 10374,
"OrderDate": "/Date(849724200000)/",
"OrderDetails": [
{
"OrderID": 10374,
"ProductID": 31
},
{
"OrderID": 10374,
"ProductID": 58
}
]
},
{
"OrderID": 10611,
"OrderDate": "/Date(869769000000)/",
"OrderDetails": [
{
"OrderID": 10611,
"ProductID": 1
},
{
"OrderID": 10611,
"ProductID": 2
},
{
"OrderID": 10611,
"ProductID": 60
}
]
},
{
"OrderID": 10792,
"OrderDate": "/Date(882815400000)/",
"OrderDetails": [
{
"OrderID": 10792,
"ProductID": 2
},
{
"OrderID": 10792,
"ProductID": 54
},
{
"OrderID": 10792,
"ProductID": 68
}
]
},
{
"OrderID": 10870,
"OrderDate": "/Date(886530600000)/",
"OrderDetails": [
{
"OrderID": 10870,
"ProductID": 35
},
{
"OrderID": 10870,
"ProductID": 51
}
]
},
{
"OrderID": 10906,
"OrderDate": "/Date(888345000000)/",
"OrderDetails": [
{
"OrderID": 10906,
"ProductID": 61
}
]
},
{
"OrderID": 10998,
"OrderDate": "/Date(891541800000)/",
"OrderDetails": [
{
"OrderID": 10998,
"ProductID": 24
},
{
"OrderID": 10998,
"ProductID": 61
},
{
"OrderID": 10998,
"ProductID": 74
},
{
"OrderID": 10998,
"ProductID": 75
}
]
},
{
"OrderID": 11044,
"OrderDate": "/Date(893269800000)/",
"OrderDetails": [
{
"OrderID": 11044,
"ProductID": 62
}
]
}
]
}
]

Deserializing JSON using JSon.NET with dynamic data

I'm trying to deserialize some JSON data into objects for an application. Up until now it's been fine because the properties on the JSON data was static (key with a value). Now I've got a result where the key is a dynamic piece of data.
Here's an example JSON url:
http://en.wikipedia.org/w/api.php?action=query&format=json&pageids=6695&prop=info
The resulting JSON for this is:
{ "query" : { "pages" : { "6695" : { "counter" : "",
"lastrevid" : 468683764,
"length" : 8899,
"ns" : 0,
"pageid" : 6695,
"title" : "Citadel",
"touched" : "2012-01-03T19:16:16Z"
} } } }
Okay, that's great except I can't deserialize the "pages" data into an object. If I were to define a class for the pages it would have to look like this:
public class 6695
{
public string counter { get; set; }
public int lastrevid { get; set; }
public int length { get; set; }
public int ns { get; set; }
public int pageid { get; set; }
public string title { get; set; }
public string touched { get; set; }
}
In order to deserialze the contents (using JsonConvert.Deserialize(jsondata)) and we all know we can't have a class called 6695. Not only that, the name of the class would have to be different (for example pageid=7145 would have to be the 7145 class).
I can seem to pluck some values out if I use something like JObject.Parse(content) and then access items as JArrays but it's pretty ugly and I'm still stuck on trying to get out the data from the pages array.
Looking for someone to help with this. I don't think it's uncommon, it's just not JSON data I've come across before and not sure how to handle it.
Thanks!
PS forgot to mention this is on Windows Phone 7 so "dynamic" isn't available!
The simplest method. In this particular case would probably be to go dynamic.
dynamic data = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(json);
var lastRevId = data.query.pages["6695"].lastrevid;
You can reference any element by it's [] name so you can do something like data["query"]["pages"]["6695"]["lastrevid"]. This will get by all those little objects where the name isn't valid in c#.
Here is how you do using https://github.com/facebook-csharp-sdk/simple-json ( https://nuget.org/packages/SimpleJson ).
var text = "{\"query\":{\"pages\":{\"6695\":{\"pageid\":6695,\"ns\":0,\"title\":\"Citadel\",\"touched\":\"2012-01-03T19:16:16Z\",\"lastrevid\":468683764,\"counter\":\"\",\"length\":8899}}}}";
(Using dynamic)
dynamic json = SimpleJson.DeserializeObject(text);
string title = json.query.pages["6695"].title;
foreach (KeyValuePair<string, dynamic> page in json.query.pages)
{
var id = page.Key;
var pageId = page.Value.pageid;
var ns = page.Value.ns;
}
(Using strongly typed classes)
class result
{
public query query { get; set; }
}
class query
{
public IDictionary<string, page> pages { get; set; }
}
class page
{
public long pageid { get; set; }
public string title { get; set; }
}
var result = SimpleJson.DeserializeObject<result>(text);
[Update]
on windows phone where dynamic is not supported and you don't want to use strongly typed classes.
var json = (IDictionary<string, object>)SimpleJson.DeserializeObject(text);
var query = (IDictionary<string, object>)json["query"];
var pages = (IDictionary<string, object>)query["pages"];
var pageKeys = pages.Keys;
var page = (IDictionary<string, object>)pages["6695"];
var title = (string)page["title"];
I hope the below example will help.
I always design a model that match the json. It is much better to work with the object when it is your own model design.
It is very easy to generate the c# model from the json. I use this website to generate the model: http://json2csharp.com
A complete example is:
C# Code:
var targetsObject = Newtonsoft.Json.JsonConvert.DeserializeObject<YourModel>(jsonString);
JSON:
{
"investors": [
{
"name": "06",
"programs": [
{
"name": "Conventional",
"value": "3.5"
},
{
"name": "FHA - Standard",
"value": "5.0"
},
{
"name": "FHA - Streamline",
"value": ""
},
{
"name": "VA",
"value": "5.5"
},
{
"name": "VA IRRRL",
"value": "6.0"
},
{
"name": "Non-Prime",
"value": ""
}
]
},
{
"name": "07",
"programs": [
{
"name": "Conventional",
"value": "3.5"
},
{
"name": "FHA - Standard",
"value": "5.0"
},
{
"name": "FHA - Streamline",
"value": "7.0"
},
{
"name": "VA",
"value": "5.5"
},
{
"name": "VA IRRRL",
"value": ""
},
{
"name": "Non-Prime",
"value": ""
}
]
},
{
"name": "08",
"programs": [
{
"name": "Conventional",
"value": "3.5"
},
{
"name": "FHA - Standard",
"value": "5.0"
},
{
"name": "FHA - Streamline",
"value": "7.0"
},
{
"name": "VA",
"value": "5.5"
},
{
"name": "VA IRRRL",
"value": ""
},
{
"name": "Non-Prime",
"value": ""
}
]
},
{
"name": "09",
"programs": [
{
"name": "Conventional",
"value": "3.5"
},
{
"name": "FHA - Standard",
"value": "5.0"
},
{
"name": "FHA - Streamline",
"value": ""
},
{
"name": "VA",
"value": "5.5"
},
{
"name": "VA IRRRL",
"value": ""
},
{
"name": "Non-Prime",
"value": ""
}
]
},
{
"name": "10",
"programs": [
{
"name": "Conventional",
"value": ""
},
{
"name": "FHA - Standard",
"value": ""
},
{
"name": "FHA - Streamline",
"value": ""
},
{
"name": "VA",
"value": ""
},
{
"name": "VA IRRRL",
"value": ""
},
{
"name": "Non-Prime",
"value": "2.0"
}
]
},
{
"name": "11",
"programs": [
{
"name": "Conventional",
"value": "3.5"
},
{
"name": "FHA - Standard",
"value": "5.0"
},
{
"name": "FHA - Streamline",
"value": ""
},
{
"name": "VA",
"value": "6.0"
},
{
"name": "VA IRRRL",
"value": "6.0"
},
{
"name": "Non-Prime",
"value": ""
}
]
},
{
"name": "12",
"programs": [
{
"name": "Conventional",
"value": "3.5"
},
{
"name": "FHA - Standard",
"value": "5.0"
},
{
"name": "FHA - Streamline",
"value": ""
},
{
"name": "VA",
"value": "5.5"
},
{
"name": "VA IRRRL",
"value": "6.0"
},
{
"name": "Non-Prime",
"value": ""
}
]
},
{
"name": "13",
"programs": [
{
"name": "Conventional",
"value": ""
},
{
"name": "FHA - Standard",
"value": "5.0"
},
{
"name": "FHA - Streamline",
"value": ""
},
{
"name": "VA",
"value": ""
},
{
"name": "VA IRRRL",
"value": ""
},
{
"name": "Non-Prime",
"value": "2.0"
}
]
}
]
}
Model:
public class Program
{
public string name { get; set; }
public string value { get; set; }
}
public class Investor
{
public string name { get; set; }
public List<Program> programs { get; set; }
}
public class RootObject
{
public List<Investor> investors { get; set; }
}
Using Json.net you can just do:
Dictionary<string,object> result = JsonConvert.DeserializeObject<Dictionary<string,object>>(json);
foreach(var item in result)
Console.WriteLine(item.Key + " " + item.Value);
How about a simple search and replace in the JSON string ? While it might not be the most elegant solution, it would possibly be the most pragmatic one.
Maybe you could just use one reserved attribute to contain the object type, and then use the base type as shown in this article: Dynamic types with JSON.NET