MVC3 JsonResult: How to disable serialization of child objects? - json

I am using ASP.NET MVC3 and one of my action methods is set up to return a Json response:
[HttpPost]
public JsonResult AddUser(User user)
{
... do something to user and return it ...
return Json(user);
While processing with Entity Framework, the user object gets a few child objects. Json serializer is likely to be unable to cope with the entire object graph, and returns InvalidOperationError error (about a circular reference being identified).
I do not need any of the child objects actually, and I would like to get user serialized without child objects. How I can achieve this?
Thank you in advance!

You can use the ScriptIgnoreAttribute to tag members you don't want serialized.

Related

Serialize/deserialize a Dictionary with a comma-separated entry

I am developing a ASP.NET Core 3.1 website and I have data in a Dictionary<string, object> that I want to Serialize/Deserialize using Microsoft System.Text.Json (I am new to Json serialize/deserialize in fact). The data comes from a PostgreSQL DB query and one of the returned values is a comma-separated list of integers (converted to string) that results from the STRING_AGG function. The image below shows one of the entries of the Dictionary:
I serialize it using the following code. Please note that I have tried both Microsoft System.Text.Json and Newtonsoft.
jsonResult = Newtonsoft.Json.JsonConvert.SerializeObject(result);
//jsonResult = JsonSerializer.Serialize(result);
The data in the Dictionary should be deserialized according to the following class structure:
I use the following code:
//IEnumerable<SeccGralContenidoViewModel> seccGralContenido = JsonSerializer.Deserialize<IEnumerable<SeccGralContenidoViewModel>>(_seccGralContenidoRepository.Read());
IEnumerable<SeccGralContenidoViewModel> seccGralContenido = Newtonsoft.Json.JsonConvert.DeserializeObject <IEnumerable<SeccGralContenidoViewModel>>(_seccGralContenidoRepository.Read());
However, an exception is thrown when deserializing no matter if I use Newtonsoft or System.Text.Json:
I am originally using System.Text.Json namespace but I also tried using Newtonsoft. After analyzing a bit deeper, I see that the problem could be the way in which data is saved to the Dictionary but I have not found a workaround.
If you don't want to write a custom converter then the simplest solution is to introduce another property:
public string CategoriasContenidolds {get; set;}
private static char delimiter = ',';
[JsonIgnore]
public string[] CategoriasContenidolds_Collection
{
get => CategoriasContenidolds.Split(delimiter).Select(item => item.Trim()).ToArray();
set => CategoriasContenidolds = string.Join(delimiter, value);
}
The serializer will use the CategoriasContenidolds property during serialization and deserialization
You should use CategoriasContenidolds_Collection (or name whatever you want) in your business logic
By explicitly marking this property with JsonIgnore the serializer will ignore that
I could solve my issue by directly getting JSON formatted results from queries. PostgreSQL does an excellent job. This way I also avoid performing a 2-step process: first, getting the query result; second, serializing to JSON.

Java Object with ArrayList<String> gets SERIALIZED as a single String rather than an Array containing one String

I have a spring boot application with the following Java Class
class Student{
int id;
ArrayList<String> subjectsTaken;
}
I make a REST call to another service where an instance of Student is passed as an entity(in the body) in the POST request. Every thing works fine when the subjectsTaken variable has multiple entries in it.
When there are multiple entries in the subjectsTaken variable, the body in the POST request is as follows
{"id":1,"subjectsTaken":["science","mathematics","history"]}
where subjectsTaken is an Array of String
but when there is only 1 entry in the subjectsTaken variable, the request body is as follows
{"id":1,"subjectsTaken":"science"}
where subjectsTaken is just a String(and not an Array with one String)
Due to this reason the Deserialization fails in the called REST service with the following error
Can not deserialize instance of java.util.ArrayList out of VALUE_STRING token.
Appreciate any pointers on this.
I think I found the solution to the problem. You can set this property in your application.properties file of the called service where the deserialization is happening.
spring.jackson.deserialization.ACCEPT_SINGLE_VALUE_AS_ARRAY=true
This helped to solve the problem.
I suggest creating an array even if its just one subject. And send this array to the rest controller.
{"id":1,"subjectsTaken":["science"]}

How to modify spring/jackson JSON deserialisation

I'm trying to figure out how to adjust the way spring/jackson convert a JSON string (stored in a file) into various POJOs. For example, if I have this JSON:
{
"rates":{
"EURUSD":5.4321,
"USDHKD":1.2345
}
}
I actually want to get an instance of my 'Rates' class. Inside that I want a List containing each individual rate.
In my spring config file I created this entry:
#Bean
public ObjectMapper jsonObjectMapper() {
return new MappingJackson2HttpMessageConverter().getObjectMapper();
}
And in my service class I did this:
#Autowired
ObjectMapper jsonObjectMapper;
public Rates currentRates() {
Resource resource = this.ctx.getResource("classpath:stub/data/rates/Rates-01.json");
return this.jsonObjectMapper.readValue(resource.getURL(), Rates.class);
}
The problem is that I am trying to figure out how to take the Map containing the currencies as a single key, break those currencies in two and then create a RateEntry object containing the two currencies and the rate, before populating a list in the Rates class.
I've been looking at Spring's Conversion Service with the idea to define a converter that maps the Map to a list. i.e. this signature: Converter<Map<String, BigDecimal>, List<Rate>>. However this is based on the assumption that the JSON is first converted to standard types before the conversion service is called. An assumption I now think is incorrect.
So I'm now trying to figure out if I need to register some sort of custom ObjectMapper to handle reading directly from the JSON String data. But that sounds like over kill as I only want to adjust part of the object graph, and let the default converters handle the rest.
Any pointers appreciated. Thanks.
Ok, Jackson tries to stay away from structural transformations (since it's a quick-sand pit with unlimited number of general permutations). But it might be possible to use some existing features to do what you want.
First: to use Object key to indicate type, you will probably want to enable polymorphic type handling with "as object wrapper" inclusion.
So add something like:
#JsonTypeInfo(as=Include.WRAPPER_OBJECT)
for your Rates class declaration.
As to converting values into list; this might work by defining "any-setter" (see http://www.cowtowncoder.com/blog/archives/2011/07/entry_458.html), something like:
#JsonAnySetter
public void set(String key, Double value) // or "Object value")
{
list.add(new Rate(key, value));
}
I hope this helps.

EF entities that contain relations (PKs,FKs) cannot be Json-ed?

I have build a very very simple database schema as
**Tickets**:
TicketId (PK)
AreaId (FK)
SeverityId (FK)
AssigneeId (FK)
**Areas**:
AreaId(PK)
AreaName
**Severities**:
SeverityId(PK)
SeverityName
**Assignees**:
AssigneeId(PK)
AssigneeName
I create the Entity Model and in the TicketController I am trying to retrieve and Json the data inside the Tickets table.
[HttpPost]
public ActionResult Index([DataSourceRequest]DataSourceRequest result)
{
var tickets = db.Tickets.Include(t=> t.Areas).Include(t=> t.Assignees).Include(t=> t.Severities)
DataSourceResult result = tickets.ToDataSourceResult(request);
Return Json(result);
}
For a reason that I cannot understand when I Json the result in order to pass it to a KendoUiGrid in the view, I get the "circular reference error". I see no circular reference in my tables/entities relations!!
In the Kendo documentation I read this
If you decide to use the Kendo UI JavaScript libraries directly,
returning JSON is simple. You just need to defined a controller
method and call this.Json on your return result. Provided .NET can
serialize your response, this is all there is to it.
Does all the above mean that in reality I cannot Json entities that come from sane database schemas with primary/foreign keys?
Thanx in advance
Create a flat Model class and pass the model to Json and Grid. You will have to populate the model a little more manually than what you are trying to do here, but there are other benefits to having a model that you will discover later. The circular reference is because of the navigational properties of your EF classes. In MVC the model does not mean the data model classes, but new ones you create. Done right the new model should do most of the work, validation, translation, etc. The controllers just passes things around, the view just renders. Hope this helps!
Try disabling lazy loading. May be it's trying to serialize everything in the DB to JSON.

How to serialize transient fields in the model via FlexJson?

I am using Play Framework to expose REST API, which returns some JSON objects.
To simplify the API usage, I would like to return a "calculated" field in the response.
Unfortunately, in my tests, while FlexJson does not ignore the transient model fields completely, but always sets them to 'null'.
More details:
In the model class, I define:
#Transient
public String currencyName;
The only constructor of the class set the value to "dollar" (for debugging purposes):
this.currencyName = "dollar";
When serializing the class using FlexJson, when the 'currencyName' field is not specified in the include/ exclude - the result always looks like:
"currencyName":null
Any idea what got wrong, and how to get the field value serialized into JSON?
Thanks in advance.
By definition if your field is transient it will not be serialized. Perhaps this field should not be transient in your application if the state matters.