How do I serialize (JSON) an object/class but not its children - c#

I have:
public Class City
{
public long ID { get; set }
...
public State State { get; set; }
...
}
public Class State
{
public long ID { get; set; }
...
public Country { get; set; }
...
}
public Class Country
{
public long ID {get; set;}
...
}
in my code I serialize a list<Country> and list<State>, etc...
The problem is if I serialize my list of Cities I get something like this:
{
"ID": 3119841,
"Name": "A Coruna",
...
"State": {
"ID": 3336902,
"Name": "Galicia",
"Country": {
"ID": 2510769,
"Name": "Spain",
...
}
...
}
...
}
this cause memory and performance issues when deserializing due to having thousands of copies of the same country object and state object, etc... what I would like to generate is:
{
"ID": 3119841,
"Name": "A Coruna",
...
"StateID": 3336902,
...
}
and then I will link up the city to the states (which I will have linked up to the country, etc.)
If I use the Ignore flag (JsonIgnoreAttribute) on the fields in the state and country classes, then I will not be able to Serialize them (I think)...
How do I achieve what I am after? (I am currently using Json.NET, but am happy to use anything that will accomplish the goal.)

To exclude a child structure from being serialized, you can use the [JsonIgnore] attribute:
public class City
{
public long ID { get; set }
...
[JsonIgnore]
public State State { get; set; }
...
}
If you want to flatten the structure, things become more complex. Your options are:
Create an intermediate flattened structure, as the result of e.g. a Linq projection.
Create a custom contract resolver for your structure, an example that may provide some inspiration on how to achieve this can be found in this question: How to flatten a referenced object into two json.net properties on the referer?
Expose the additional properties of your State class that you want to "flatten" in the City class as properties:
public long StateID { get { return State.ID; } }
Note that some frameworks will also require you to add the [ScriptIgnore] and/or [NonSerialized] attributes, in addition to or as alternatives of the [JsonIgnore].

You add [NonSerialized] attribute on top of that field.
To have a plain object (no childs), you can create a model for that object and map the required properties.
public class City
{
public long ID { get; set }
...
[NonSerialized()]
public State State { get; set; }
...
}
To have a plain object (no childs), you can create a model for that object and map required properties (only the properties you need).
public class CityModel
{
public long ID { get; set }
public string Name { get; set; }
...
public long StateID { get; set; }
...
}
Now we map the required properties. (this can be in a function that you can use when you want)
var cityModel = new CityModel {
ID = city.ID,
Name = city.Name,
...
StateID = city.State.ID
...
}

You can ignore the State property using JsonIgnore and have an additional property called StateID which gets its value from the State object.
public Class City
{
public long ID { get; set }
...
public int StateID
{
get
{
return State.ID;
}
}
[JsonIgnore]
public State State { get; set; }
...
}

I believe your most appropriate solution is follows; first, add all the required attributes to refuse serialization on your State object (which set you use totally depends on what serailizer you use):
JsonIgnore: http://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_JsonIgnoreAttribute.htm
ScriptIgnore: https://msdn.microsoft.com/en-us/library/system.web.script.serialization.scriptignoreattribute%28v=vs.110%29.aspx
NonSerialized (fields only): https://msdn.microsoft.com/en-us/library/system.nonserializedattribute%28v=vs.110%29.aspx
After doing so, I recommend you add a property that can manipulate the state object by ID:
public class City
{
public long ID { get; set; }
...
[JsonIgnore, ScriptIgnore]
public State State { get; set; }
public long StateID
{
get { return State.ID; }
/* Optionally include a set; some JSON serializers may complain in
absence of it, up to you to experiment with */
set { State = new State(value); }
}
...
}
This completely preserves your structure, and a well-designed constructor in State can handle accepting an Id and building a State object from it. If you can't build a State object from Id alone, and your JSON Serializer requires a set mutator on it, then you could simply empty the body of it.
You can expand this to your other objects as well:
public class State
{
public long ID { get; set; }
...
[JsonIgnore, ScriptIgnore]
public Country Country { get; set; }
public long CountryId
{
get { return Country.Id; }
set { Country = new Country(value); }
}
...
}
The major advantage to this model, is that if you do it correctly and design State and Country appropriately, your JSON Serializer will do all the heavy lifting.
Also, as Alex mentioned, you may also create Contract Resolvers, though this is extra work.

This all really depends on your data set. When dealing with a large dataset, I simply use the [JsonIgnore] flag on the property. From there, I would request the cities and states async. I would put the states in a IEnumerable, and then use a LINQ query to populate the IEnumerable of cities.
Something like this:
Cities.ToList().ForEach((c) =>
{
c.State= States.FirstOrDefault(x => x.Id == c.StateId);
});
Also, I tend to use virtual properties to reference other objects like State.
Something like this:
public class City
{
public int Id { get; set; }
public string Name { get; set; }
[Required]
public int StateId { get; set; }
[JsonIgnore]
[ForeignKey("StateId")]
public virtual State State { get; set; }
}
public class State
{
public int Id { get; set; }
public string Name { get; set; }
}
If I have a localdb at my disposal, then I would use a different solution.
If it's a small enough dataset, I just serialize the whole object and let JSon.Net do the heavy lifting.
I'm pretty sure you cannot use [NonSerialized] with a custom class property. At least, it threw an error on my-side.

You can use [ScriptIgnore]:
public Class City
{
public long ID { get; set }
...
[ScriptIgnore]
public State State { get; set; }
...
}

Related

How to completely remove a property from an Object in c#

someone, please tell me the most straightforward syntax to remove a property from a c# object. I don't know why it is not clear on the internet.
{
"id": 1,
"name": "string",
"email": "string",
"cities": []
}
this is the response I get upon calling the get API. I want to remove the cities array, but I don't know why everything is so complicated in c#. I expect a magical short syntax like delete(in JS). Remember that this response is a dbContext response, not a standard object(DTO).
if you going to deserialize json, you can just create a class without cities property
public class Data
{
public int id { get; set; }
public string name { get; set; }
public string email { get; set; }
}
or if you can not change the class properties, just add an ignore attribute
using Newtonsoft.Json;
public class Data
{
.....
[JsonIgnore]
public List<object> cities {get; set;}
}
the code
Data data= JsonConvert.DeserializeObject<Data>(json);
if you want to remove only from json
var jsonParsed = JObject.Parse(json);
jsonParsed.Properties()
.Where(attr => attr.Name == "cities")
.First()
.Remove();
json=jsonParsed.ToString();
first, you can not change the class structure in runtime in C#.
you should define new object with your properties in mind, or use dynamic-expando objects to be able to manipulate object at runtime.
if your issue is only when you want to sterilize your object you can use [JsonIgnore] Property on the model:
public class MyDto
{
public int id { get; set; }
public string name { get; set; }
public string email { get; set; }
[JsonIgnore]
public string[] cities { get; set; }
}
this will tell you serializer to skip that property.
if you want to convert ur already define class to a dynamic object there are lots of ways.
you can use this nugget package that I wrote which have a DeSelect() method that returns a dynamic object without the specified properties:
https://www.nuget.org/packages/linqPlusPlus/1.3.0#readme-body-tab

Mapster - Dynamic property selection or ignore

I have a business need to dynamically select ONLY the properties of a given model that are specified, similar to an OData select clause. I am currently using Mapster's ProjectToType functionality to populate view models from EF Core entities.
Is there any way to tell Mapster to only select a given list of properties in the query that it generates? Or a way to take the full model mapping, and change mappings at runtime in an instance of TypeAdapterConfig to ignore properties that aren't in a given list of properties?
The end solution needs to be generic and work with navigation properties, because it will be applied to all of our entities in the database. We also used DynamicLinq in some cases, not sure if that can be used on top of Mapsters ProjectToType functionality.
Example:
Entities (Some properties omitted for length):
namespace DataAccess.Entities
{
public class Series
{
public Guid Id { get; set; }
public string Description { get; set; }
public long? StackRank { get; set; }
public string EntityId { get; set; }
// Other properties
}
public class Model
{
public Guid Id { get; set; }
public string Description { get; set; }
public string EntityId { get; set; }
public long? StackRank { get; set; }
public Guid SeriesId { get; set; }
public virtual Series Series { get; set; }
// Other properties
}
}
View Models (Some properties omitted for length):
namespace Models
{
public class Model
{
public Guid Id { get; set; }
public string Description { get; set; }
public string EntityId { get; set; }
public long? StackRank { get; set; }
public Guid SeriesId { get; set; }
public virtual Series Series { get; set; }
// Other properties
}
public class Series
{
public Guid Id { get; set; }
public string Description { get; set; }
public long? StackRank { get; set; }
public string EntityId { get; set; }
// Other properties
}
}
Given a rest call to get a list of all Model view models, with this list of properties to include:
var properties = new List<string> {
"Id",
"EntityId"
"Description",
"Series.Id",
"Series.Description",
"Series.EntityId"
}
The results would return some type of dictionary, dynamic, or anonymous object that contained ONLY these properties, and the other properties would not even be included in the final select of the SQL query that gets created.
In the end, I decided to use Arca Artem's suggestion, with a little twist. I used reflection to grab a list of all properties of the model and cache them. After that, I compared the cached properties vs the list of properties to include, and ignored the properties that weren't in both lists. Kinda like this:
var clonedConfig = mapsterInstance.Clone();
clonedConfig.ForType<TSource, TDestination>().Ignore(propertiesToIgnore);
var models = await query.ProjectToType<TDestination>(clonedConfig).ToListAsync();
Maybe not the most elegant solution, but it worked well enough for what I needed. I also set up our json serializer to ignore null values.

Filling list with different types of objects

I'm working on a recommendation algorithm which all works fine. But now I wanted to implement this code into the branch of my development team.
I'll start from the top. My algorithm can recommend 2 types of objects, restaurants and dishes.
Restaurant:
public class Restaurant
{
public Guid Id { get; set; }
public string Name { get; set; }
public Address Address { get; set; }
public List<Tag> Tags { get; set; } = new List<Tag>();
public int PriceRange { get; set; }
}
And dish:
public class Dish
{
public Guid Id { get; set; }
public string Name { get; set; }
public double Price { get; set; }
public virtual Restaurant rest { get; set; }
[ForeignKey("rest")]
public Guid RestaurantId { get; set; }
public List<Tag> Tags { get; set; }
}
Now my product owner wants the list to be like this when it's being presented on the home page of our app:
[Restaurant][Dish][Restaurant][Dish] Etc...
So basically, he wants to alternate the type of object that's being recommended. These dishes and restaurants are completely separate. They are generated by my algorithm purely on the user's preferences and have no correlation with eachother at all.
Now my problem is how to return such a list. I figured I'd need a wrapper class which contains either a Restaurant or Dish like this:
public class RecommenderItem
{
public Restaurant rest { get; set; }
public Dish dish { get; set; }
}
This way I can create a List<RecommenderItem> and return that to the client. The client would only need to check which attribute is null and retrieve the values from the one that is not.
I'm just unsure if this is the correct approach. Are there any 'best practices' in doing this? Let me know if I should elaborate more!
If they doesn't have common base class then creating one wrapper class is the best solution. At the same time you can be more flexible and create something like
public class RecommendationItem
{
public Guid Id { get; set; }
public string Name { get; set; }
public string PageUrl { get; set; }
public object Entity { get; set; }
}
So you can include all common information in this class and client will not be required to check with which object type he works. In such case it would be easier to add one more item type. At the same type I added reference to entity itself - it can be used if some specific handling for one or two item types is required.
You can declare an interface IRecommenderItem:
public interface IRecommenderItem
{
//shared properties
}
public class Restaurant : IRecommenderItem
{
}
public class Dish : IRecommenderItem
{
}
than, you can type:
List<IRecommenderItem> m = new List<IRecommenderItem>();
If you are going to connect pairs of elements it always makes sense to me to... well, pair the elements. I am assuming that each dish is specific to a particular restaurant? So the list would be [Restaurant1][Dish for Restaurant1][Restaurant2][Dish for Restaurant2]...?
I like the previous answer by oryol creating a common base class as well.
So, your RecommenderItem class is fine. But fill in both properties and pass a list of pairs back. Expand the list into the full set of items for display by creating a new List, iterating through the list of RecommenderItems and adding Restaurant and Dish from each entry in it.

Proper domain model design

Given an Employee entity and bunch of personal/organization-related information (like marital status, children information, department, position). Is all personal information to be represented as components/value objects or it is better for the information to reside inside the entity class?
Would using a person (which could gather all personal info) value object as an underlying object (composition) for an Employee entity be a bad design choice?
Also how would such a behaviour modelled properly (in terms of DDD): If employee has kids then it should have a birth certificate (with corresponding data: name, issue date, etc) or If employee is married then it should have marriage certificate (with corresponding data: spouse name, etc)?
For a kids case I decided to use ChildrenInformation value object:
public class ChildrenInformation
{
public String BirthCertificateCode { get;set; }
public DateTime BirthCertificateIssueDate { get;set; }
public ChildName { get; set; }
public ChildMiddleName { get; set; }
public ChildLastName { get; set; }
public DateTime ChildBirthday{ get; set; }
}
public class Employee : AbstractEntity<Employee>, IAggregateRoot
{
public ISet<ChildrenInformation> ChildrenInformation { get; set; }
/* other things ...*/
}
Wouldn't it be wrong from a design view?
EDIT
Another thought is to share Certificate class.
[Serializable]
public class Certificate
{
public String Code { get; set; }
public String Number { get; set; }
public String RegistreeName { get; set; }
public Address RegistreeAddress { get; set; }
public String RegistreeDateOfBirth { get; set; }
public String RegistredAt { get; set; }
public DateTime DateRegistred { get; set; }
}
[Serializable]
public class Employee : AbstractEntity<Employee>, IAggregateRoot
{
public Certificate Passport { get; set; }
public Certificate MarriageCertificate { get; set; }
public ISet<Certificate> ChildrenBirthCertificates { get; set; }
}
Thanks!
I would model it like this:
public class Person
{
public String Name { get; set; }
public String MiddleName { get; set; }
public String LastName { get; set; }
public DateTime Birthday { get; set; }
public BirthCertificate BirthCertificate { get;set; }
public MarriageCertificate MarriageCertificate { get;set; }
// ...etc...
}
public class Certificate
{
public String Code { get;set; }
public DateTime IssueDate { get;set; }
// ...etc...
}
public class BirthCertificate: Certificate
{
public DateTime BirthDate { get;set; }
// ...etc...
}
public class MarriageCertificate: Certificate
{
public String SpouseName { get;set; } // or Spouse could also be a person
// ...etc...
}
public class Employee
{
public ISet<Person> Children { get; }
// ...etc...
}
Some points:
Note the ? usage which means certificates are optional.
Certificate deserve their own types. If you have more than one property that start with the same prefix, most of the time, it means you can define an object off them. I have also created a base Certificate class because they may share some common properties and behavior.
Children is a collection of Person objects.
Spouse could also be a person, if you will (the property would then be named Spouse).
I don't repeat the declaring type name in a property name: Name instead of PersonName
Given an Employee entity and bunch of personal/organization-related information (like marital status, children information, department, position). Is all personal information to be represented as components/value objects or it is better for the information to reside inside the entity class?
I would put all of the given examples as properties in the employee entity. I don't see any benefit in having them as value objects?
Would using a person (which could gather all personal info) value object as an underlying object (composition) for an Employee entity be a bad design choice?
This is more of a domain question. I normally do not use inheritance but use Customer and Employee (instead of a Person entity) as to different models not related to each other.
Please note that the design concept of composition has nothing to do with the CLR concept of a value type. Composition just means that the life-time of the owned object is bound to the life-time of the owner. This can also be achieved with reference types, for example if the owner is the only one with a reference to the owned object.
That said, the solution from Simon is just fine.

What is the equivalent of <composite-element> in Castle ActiveRecord?

I have a TrackLog that has a collection of TrackPoints:
public class TrackLog
{
public string Name { get; set; }
public ISet<TrackPoint> TrackPoints { get; set; }
}
public class TrackPoint
{
public DateTime Timestamp { get; set; }
public double Latitude { get; set; }
public double Longitude { get; set; }
}
I'd like to map the track points as a collection of components, as this makes the most sense. According to the book NHibernate in Action, on page 187:
Collections of components are mapped similarily to other collections of value type instances. The only difference is the use of <composite-element> in place of the familiar <element> tag.
How would I do this using Castle ActiveRecord attributes?
Solution:
To expand on Mauricio's answer, the correct mapping is like so:
[ActiveRecord]
public class TrackLog
{
[Property]
public string Name { get; set; }
[HasMany(DependentObjects = true,
MapType = typeof(TrackPoint),
Table = "TrackPoint",
ColumnKey = "TrackLog_Id"
)]
public ISet<TrackPoint> TrackPoints { get; set; }
}
You must provide the MapType, Table, and ColumnKey properties in addition to DependentObjects.
MapType: the type of the class you want to map to
Table: name of the table in the database for the component list
ColumnKey: name of the foreign key column used to relate the child to the parent
Update:
You cannot use Set as the RelationType. It will cause NHibernate to exhibit some weird behavior, where it saves the entities, deletes them, and the re-saves two copies of each element. In the case of my TrackLog, it saved 25 TrackPoints, deleted them, then saved the 25 TrackPoints again two times, for a total of 50. Then when the SessionScope was disposed, it saved another 25, for a total of 75 TrackPoints instead of the expected 25. I couldn't find out the source of this problem, but the fix is to avoid using Set and use Bag (or something else, I only tested it with Bag) instead.
Use DependentObjects = true, e.g.:
public class TrackLog {
[Property]
public string Name { get; set; }
[HasMany(DependentObjects = true)]
public ISet<TrackPoint> TrackPoints { get; set; }
}

Categories