I have problem with JsonConvert deserializer. I have class
[BsonCollection("matches")]
public class MatchData : Document
{
[JsonPropertyName("id")]
public string ExternalMatchId { get; set; }
...
}
In my controller, I am trying to deserialize in this way:
[HttpPost("end")]
public ActionResult RoundEnd([FromBody] dynamic data)
{
var saveData = JsonConvert.DeserializeObject<MatchData>(data.ToString());
...
}
Input JSON looks like
"{"id": "61696f268c7b70b5f3e85803",
"game_server_id": "615ed4a1cd95e8209a4ab67d",
...
But in my output MatchData object ExternalMatchId is null. How to fix that?
You are mixing frameworks here. The JsonPropertyName attribute is for the System.Text.Json namespace whereas you are using JSON.Net to deserialise. So the solution is to stick with one of them. Either deserialise with the built in framework:
System.Text.Json.JsonSerializer.Deserialize<MatchData>(data.ToString());
Or switch the attributes to use the JSON.Net versions:
[JsonProperty("Foo")]
Having said all that, it looks like you can simplify the whole thing by getting MVC to do the work for you. Instead of using dynamic as the model (don't do that - dynamic is problematic and every time you use it a kitten dies), put the model in here directly:
public ActionResult RoundEnd([FromBody] MatchData data)
I have some problems while using Entity Framework.
I always use a JSONHelper class to convert a list of string to JSON.
Here is the JSONHelper Class:
public static class JSONHelper
{
public static string ToJSON(this object obj)
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
return serializer.Serialize(obj);
}
public static string ToJSON(this object obj, int recursionDepth)
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
serializer.RecursionLimit = recursionDepth;
return serializer.Serialize(obj);
}
}
This class creates JSON. But sometimes it gives me an error saying that "A circular reference was detected in Entity..........."
So in some of the properties of the classes that entity-framework created for me, I have to use [ScriptIgnore] Attribute. Then it works fine.
Now, let's say I made a small change in database. So I will refresh my ADO.Net Entity Data Model. Then I again have to open all those class files and write [ScriptIgnore].
So, I decided to make a change in template designer. But I could not find the files that entity framework uses to create my POCO classes.
Any Ideas????
Please don't tell me to change the way of converting List to JSON.
I recommend that you use the NewtonSoft.Json serializer. It works very well and has settings options for handling many things, including circular references. There is a lot of good documentation and help available for that serializer. Don't reinvent the wheel.
Circular references are controlled like this:
SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
I believe this answer describes what you need to do.
For any entity which you need to apply the ScriptIgnore attribute, you can make a partial class which does the attribute decoration.
Say your entity is like this
public partial class Entity
{
public int Id { get; set; }
public string Name { get; set; }
}
You can create a separate partial class like this
public interface IEntity
{
[ScriptIgnore]
string Name { get; set; }
}
public partial class Entity:IEntity
{
}
You can achieve this by modifying the T4 template file (.tt file). Take a look at the .tt file in a text editor and you will be able to see where your properties are being created. Insert the [ScriptIgnore] attribute in your template and it will be automatically included when you re-generate your entities.
You might need to include an appropriate 'using' at the top of the template etc.
You can do a lot by editing the T4 template, we used it to automatically have our entities implement INotifyPropertyChanged for all properties.
So I am new to working with MVC4 and the serialization of objects on the back end seems pretty "magical" to me so if I am doing this the wrong way please let me know.
My goal however is to build a simple rest API and return JSON out. I figured that I would use System.Json and just return JsonObject. I have simplified this down for the sake of this question but the objects are much more complicated in my real issue.
Here is my controller....
....
public class ActionsController : ApiController
{
// GET api/actions
public JsonObject Get()
{
JsonObject testObjet = new JsonObject();
testObjet.Add("Name", "Test name");
testObjet.Add("Description", "Test Description");
return testObjet;
}
....
I would expect to see:
{"Name":"Test name","Description":"Test Description"}
Instead I see:
{"Name":[],"Description":[]}
I actually seem to get better results when I return a string of the JsonObject or heck even just return the object itself with the exception it has enums and I want to return the names not the number values, which is what led me to JsonObject for customization.
Does anyone know why it is dropping off the values?
EDIT:
So because of Dan's comments below I tried just for giggles to see what the XML serializer spit out with the JSON object and I get the below exception...
"Type 'System.Json.JsonPrimitive' with data contract name 'JsonPrimitive:http://schemas.datacontract.org/2004/07/System.Json' is not expected."
So it appears that you can not serialize the System.Json.JsonObject object, because it uses a type that it does not expect.
That is shocking. Does anyone have a workaround? If not I am off to find out how to show enum names when serializing instead of values.
So the answer is apparently... You Can't!
It appears that the type JsonPrimitive is not supported to serialize objects. The answers provided below by Obi and Dan helped me to poke around a bit more and find out that the XML serializer actually throws an exception while the JSON serializer simply eats it and puts out an empty array which is what you see above.
There are any number of correct answers here.
Make your own custom serializer
Output JSON as a string
Return custom objects and then work around things like the Enum
values
I am sure there are others.
But whatever you do don't try to use System.Json as a return in the ApiController because you will get the results above.
You should not force your WebApi call to use a particular format like JSON. One of the features of WebApi is that you can specify the format as part of the request. Return an object from your Get call, and let the WebApi engine do the serialization and deserialization:
public class DataObject
{
public string Name { get; set; }
public string Description { get; set; }
}
public class ActionsController : ApiController
{
// GET api/actions
public DataObject Get()
{
var testObject = new DataObject
{
Name = "Test name",
Description = "Test Description"
};
return testObject;
}
}
You can specify the format by setting the Accept header to application/xml, application/json, etc.
The default JSON serializer has no problem serializing simple string properties like Name and Description.
I would suggest you did this instead
// GET api/actions
public object Get()
{
//New up a strongly typed object if you want to return a specific type
//and change Action return type accordingly
var testObjet = new (){
Name= "Test name",
Description= "Test Description"
};
return testObjet;
}
Dan has posted a similar answer below so let me try to address your other problem. To serialize the enum, I would suggest you hide it in a public string property which would return the string value of the enum,
public class DataObject{
public MyEnum SomeEnumValue;
public string EnumValue{
get {
//..return SomeEnumValue string value
}
}
}
You can then read the value from EnumValue which should be properly serialized as you want.
this is my JSON
[{"id":23,"name":"Video Clips"},{"id":15,"name":"Deleted Scenes"},{"id":9,"name":"Music Albums"},{"id":7,"name":"Trailers"},{"id":18,"name":"Short Films"},{"id":21,"name":"Movie Clips"},{"id":1,"name":"Movies "},{"id":4,"name":"Plays"},{"id":22,"name":"Scenes"},{"id":2,"name":"TV Show"},{"id":5,"name":"Kids"},{"id":16,"name":"Interviews"},{"id":11,"name":"Film Songs"},{"id":14,"name":"Making of Movie"}]
I have to deserialize it how should I do this? please help
The JSON you have there represents an array of objects which look like Videos so first you will need to define a class to store each video like so:
public class Video
{
public int ID { get; set; }
public string Name { get; set; }
}
With this done you can make use of one of the many JSON libraries either built in or third party. For this example I have made use of JSON.NET. Here is a link to the documentation.
Next you will need to make use of the DeserializeObject static generic method of the JsonConvert class like so, specifying the List<Video> type so that it knows the JSON to be de-serialized is a collection of Video objects:
using Newtonsoft.Json;
...
string json = "[{\"id\":23,\"name\":\"Video Clips\"},{\"id\":15,\"name\":\"Deleted Scenes\"},{\"id\":9,\"name\":\"Music Albums\"},{\"id\":7,\"name\":\"Trailers\"},{\"id\":18,\"name\":\"Short Films\"},{\"id\":21,\"name\":\"Movie Clips\"},{\"id\":1,\"name\":\"Movies \"},{\"id\":4,\"name\":\"Plays\"},{\"id\":22,\"name\":\"Scenes\"},{\"id\":2,\"name\":\"TV Show\"},{\"id\":5,\"name\":\"Kids\"},{\"id\":16,\"name\":\"Interviews\"},{\"id\":11,\"name\":\"Film Songs\"},{\"id\":14,\"name\":\"Making of Movie\"}]";
List<Video> videos = JsonConvert.DeserializeObject<List<Video>>(json);
With this done you have a collection of Video objects to work with.
Hope this helps you.
You can deserialize the json using JavaScriptSerializer from the System.Web.Extensions dll which can be found in:
C:\Program Files\Reference
Assemblies\Microsoft\Framework.NETFramework\v4.0\System.Web.Extensions.dll
After adding a reference to the DLL in the project add:
using System.Web.Script.Serialization;
And you will also need to set Target Framework to a non-Client Profile, for example:
.NET Framework 4
Then use code like this one to deserialize the json:
var json = #"[{""id"":23,""name"":""Video Clips""},{""id"":15,""name"":""Deleted Scenes""},{""id"":9,""name"":""Music Albums""},{""id"":7,""name"":""Trailers""},{""id"":18,""name"":""Short Films""},{""id"":21,""name"":""Movie Clips""},{""id"":1,""name"":""Movies ""},{""id"":4,""name"":""Plays""},{""id"":22,""name"":""Scenes""},{""id"":2,""name"":""TV Show""},{""id"":5,""name"":""Kids""},{""id"":16,""name"":""Interviews""},{""id"":11,""name"":""Film Songs""},{""id"":14,""name"":""Making of Movie""}]";
var jsonSerializer = new JavaScriptSerializer();
var deserializedList = jsonSerializer.Deserialize<List<JsonType>>(json);
I am trying to return an Entity Framework 4 object with children to an jQuery JSON AJAX function but I get a circular reference error - in short my method looks like this
[WebMethod]
public static JSONObject Get()
{
WebHelper.JSONObject lJSONObject = new WebHelper.JSONObject();
lJSONObject.Object = Repository.Parent.Include("Child.Child").FirstOrDefault();
return lJSONObject;
}
if I do not include children the functions works fine, but with children the circular reference occurs. Any ideas what I can do to fix this?
Do you have to return a JSONObject? If not, you can try using Json.NET, which will handle circular references properly:
var settings = new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
};
JsonConvert.SerializeObject(object, Formatting.Indented, settings);
My guess is that the JsonObject is simply a wrapper that will serialize the entity and put it on the response stream, which is simple enough to do manually.
Try adding ScriptIgnore attribute to property Parent. See for more details: http://msdn.microsoft.com/en-us/library/system.web.script.serialization.scriptignoreattribute.aspx
-- EDIT --
They will be overwritten if you do this in designer file. But you can try adding metadata type:
[MetadataType(typeof(TestMD))]
public partial class Test
{
}
public class TestMD
{
[ScriptIgnore]
public object Parent { get; set; }
}
I had the same problem. Not sure if there's any other solution, but I got it to work creating my own Serialize method.