How can I remove a property from an list/array of a object?
My model contains:
public string FirstName { get; set; }
public string LastName { get; set; }
public string Age { get; set; }
public string Size { get; set; }
And i'm converting this to JSON with
string json = JsonConvert.SerializeObject(client);
And all works fine... I got all propertys of the object in JSON.
But I need to create two levels of acess, and show all info in one level, and the other level, fewer propertys...
My question is: Can I remove a property of an object?
Someting like this:
List<Customer> customers = new List<Customer>();
//(and this have 100 clients inner)
customer.removeProperty(Age, Size); // Can I have someting like this?
Try using the json ignore tag above the property. E.g.:
[JsonIgnore]
public string Age { get; set; }
If you want to be able to serialise both with and without certain properties, without altering the structure of your actual classes, you could try using the example here.
Create a new model with your fewer properties. Make two lists, one with all the properties and the other with the properties you want removed.
For example
public YourModelNow
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Age { get; set; }
public string Size { get; set; }
}
public YourModelNowFiltered
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
This is assuming you need two file.json with the different properties. If you just need to ignore the properties use Ross Gurburts approach.
i would suggest using AutoMapper
you will need to create a DTO [Data Transfer Object] class
which would have the properties that you would like to expose
the usage is pretty simple:
in the config:
var config = new MapperConfiguration(cfg => {
cfg.CreateMap<YourModel, YourModelDTO>();
});
in the actual usage:
IMapper iMapper = config.CreateMapper();
var source = new YourModel();
var destination = iMapper.Map<YourModel, YourModelDTO>(source);
for more information and example of what AutoMapper could do read here
Related
I have a master object where it contains list of properties and these properties have their attributes. I like to copy these object's properties to a new one but omitting some of its properties.
How do you do this? could this be done using ExpandoObj? Removing the properties should be hundle during runtime because in the UI part there are checkbox on which properties to include. If the property is not checked then it should not be including in the creation of the object.
Update: properties have their attributes, [Workbook(Order = 1)], I want this to be copied also as it contains information determining how its value can be translated.
As others have stated, it might be better if you can change your approach. But of course this is not always possible, sometimes the other object class is in a library that you can't change or don't want to change for example.
A simple (but maybe not very efficient so take care) approach is to serialise and deserialise with JSON.
(I know this is technically abuse, and not necessarily efficient in terms of performance, but it is simple).
//Your master class
public class Master
{
public Boolean Enabled { get; set; }
public string Name { get; set; }
public string Status { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string Address3 { get; set; }
public string City { get; set; }
public string Postcode { get; set; }
public string Country { get; set; }
public Master ()
{
}
}
//Your simplified class
public class Simple
{
public Boolean Enabled { get; set; }
public string Name { get; set; }
public string Status { get; set; }
public Simple()
{
}
}
//Code to transform
Master mstr = new Master() { Address1 = "Castle rose", Address2 = "The street", Address3 = "Done the lane", City = "Ebson on the Hill",
Country = "UK", Postcode = "NR1 1YT", Enabled = true, Name = "John Jones", Status = "Activated" };
string json = JsonConvert.SerializeObject(mstr);
Simple simp = JsonConvert.DeserializeObject<Simple>(json);
This is handy, especially if you are doing a PoC or testing etc. and you want something quick but simple. But a better permanent solution is to have a new Constructor of your Simple Class which would accept a Master as input and only copy the attributes it requires.
Or you could use reflection, which might offer more flexibility but also has a performance overhead, so you have to be careful where and how you use it.
What is a good way is to automap an object with some properties, one of which is a JSON string, to another object where that JSON string would be represented by properties instead of JSON.
See the source and destination classes below for an example:
CustomJson will look something like this for this example but could be different for other AlertTypes: { "AlertPrice": 500.0 }
//This is the database table representation (source)
public class Alert
{
public int Id { get; set; }
public int UserId { get; set; }
public string AlertType { get; set; }
public string CustomJson { get; set; }
}
//This is the business logic model (destination)
public class UserAlert
{
public int Id { get; set; }
public int UserId { get; set; }
public string AlertType { get; set; }
//This comes from the CustomJson string in the DB
//A different AlertType may need to map to a different object with different properties
public decimal AlertPrice { get; set; }
}
Will a ValueResolver allow me to do this or will it only be able to map part of the object? If not, perhaps I should just have a Custom property which contain the custom info instead of trying to meld it into the top-level object.
CreateMap<sourceobject, destobject>()
.AfterMap((src, dest) =>
{
dest.AlertPrice = JsonConvert.DeserializeObject<T>(json).AlertPrice;
});
CreateMap<sourceobject, destobject().AfterMap((src, dest) =>
{
dest.AlertPrice = decimal.Parse(src.AlertPrice, CultureInfo.InvariantCulture);
});
Please use above code you have use Explicity Mapping
I have an API that returns some data of a class in JSON. Is there any way to return only some specific fields of a C# class in JSON?
For example:
class Person {
public int Id{ get; set; }
public string Name { get; set; }
public string Family { get; set; }
public string Gender { get; set; }
}
Person myPerson = new Person();
var Json = (new
{
Person = myPerson
});
return Request.CreateResponse(HttpStatusCode.OK, Json);
It returns ID, Name, Family, Gender. I need to return only the Name and Family. I thought I can create an object and add my specific fields in the class in that object and return object?
Use anonymous types?
return Request.CreateResponse(HttpStatusCode.OK, new {Name = person.Name; Family = person.Family});
You should consider applying the DRY principle.
The DRY principle is not "never write code twice", but rather that "every piece of knowledge must have a single, unambiguous, authoritative representation in the system".
What this means is that you have to build a model that has a meaningful name, contains properties that it actually has, and can be changed as needed later without having to figure out where else in the application it's used. I'm certain you could also find a name that would better represent this area of the application.
Should I create a different model with just the properties I need or
use the same model and have NULL values for the field I don't use? Or just create anonymous type and make this way harder in future?
I don't recommend using the same model for your case, from my understanding of it. It's going to make your life easier down the road if you build a model that has a meaningful name as I said before.
So what should we do? I have seen many people trying to use JsonIgnore in domain model but you should not get down that path. You should avoid using JsonIgnore in domain model. I will give an example for it.
For example:
class Person {
public int Id { get; set; }
public string Name { get; set; }
public string Family { get; set; }
public string Gender { get; set; }
}
So you have this model and you want other models to inherit from it but like in your case you don't want to return Id and Gender, only Name and Family. So you go like this.
class Person {
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual string Family { get; set; }
public virtual string Gender { get; set; }
}
public class PersonNameModel : Person {
[JsonIgnore]
public override int Id { get; set; }
[JsonIgnore]
public override string Gender{ get; set; }
}
If a class has many properties and you only want to serialize a small
subset of them then adding JsonIgnore to all the others will be
tedious and error prone. The way to tackle this scenario is to add the
DataContractAttribute to the class and DataMemberAttributes to the
properties to serialize. This is opt-in serialization, only the
properties you mark up with be serialized, compared to opt-out
serialization using JsonIgnoreAttribute.
But, you can do it with the help of JsonIgnore but this way does not support XML format. So, in case your application has to support XML format more (or only support XML), instead of using Json.Net, you should use [DataContract] which supports both JSON and XML.
Datacontract is a great solution. It gives me a clean REST API. At the same time when I save the data in a no-sql, the ignored properties are persisted despite the objects being stored as json.
[DataContract]
public class Person {
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual string Family { get; set; }
public virtual string Gender { get; set; }
}
public class PersonNameModel : Person {
// included in JSON
[DataMember]
public override string Name { get; set; }
[DataMember]
public override string Family { get; set; }
// other inherited properties will be ignored
}
I will also mention another way of doing it as there are more (custom contact resolver, Web API convention ("ShouldSerialize")...)
Another way you can do it is to decorate your auto property with JsonProperty attribute in order to skip the serialization of that field if it is null.
Example:
class Person {
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public int? Id { get; set; }
public string Name { get; set; }
public string Family { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string Gender { get; set; }
}
Happy coding!
I have this simple data model:
// Model
public class Address
{
public string Street { get; set; }
public string City { get; set; }
public string State { get; set; }
public string ZipCode { get; set; }
.... Another values here ....
}
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public Address Address { get; set; }
.... Another values here ....
}
// ViewModel
public class PersonViewModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Street { get; set; }
public string City { get; set; }
public string State { get; set; }
public string ZipCode { get; set; }
}
I want to map (using AutoMapper) the values of PersonViewModel to the corresponding properties (where AutoMapper discovers if the property should be in the root object or inside the sub-object). Keeping in mind, AutoMapper should not create neither Person object nor Address (the objects must be created manually to fill another properties before auto mapping), and AutoMapper uses the already existed objects. For example:
var addressObj = new Address
{
... Filling some values...
};
var personObj = new Person
{
Address = addressObj;
... Filling some values...
};
mapper.Map(personViewModelObj, personObj); // How to make this work for both Person and Address properties?
How can I get that auto mapping to work for both person properties and address properties?
Should I add two mapping rules (for address and for person), and execute mapper.Map() twice?
Using #Jasen comments I got it working. The main problem was that I am mapping in a reversed direction. This sentence in official documentation solves the problem:
Unflattening is only configured for ReverseMap. If you want unflattening, you must configure Entity -> Dto then call ReverseMap to create an unflattening type map configuration from the Dto -> Entity.
Here is the link:
https://github.com/AutoMapper/AutoMapper/blob/master/docs/Reverse-Mapping-and-Unflattening.md
In other words, to get unflattering to work, I have (or must) to map in this direction:
CreateMap<HierarchicalObject, FlattenedObject>()
.ReverseMap();
I'm using the official MongoDB C# Driver to communicate with my MongoDB Servers.
This is my complete entity scheme:
public class Person
{
public ObjectId _id { get; set; }
public String FirstName { get; set; }
public String LastName { get; set; }
public DateTime DateOfBirth { get; set; }
public List<Address> Addresses { get; set; }
}
public class Address
{
public String Street { get; set; }
public String City { get; set; }
}
Now, in several cases i just want to get the following return:
public class Person_LocationOview
{
public String LastName { get; set; }
public List<Address_CityOnly> Addresses { get; set; }
}
public class Address_CityOnly
{
public String City { get; set; }
}
The default behavior to load all fields and do the mapping by myself
MongoCursor<Person>
is senseless, because I just want to load the specific fields.
With the help of reflection I generate the fields to load and send:
var fields = new { "LastName", "Addresses.City" };
MongoCollection< BsonDocument >.FindAllAs< Person_LocationOview >( )
.SetFields( fields ).ToList( );
I thought the serializer of MongoDB would be intelligent; but the call returns following error:
System.IO.FileFormatException: Required element 'City' for property 'City' of class Models.Address_CityOnly is missing
Any ideas to this requirement?
I've updated the complete MongoDB infrastructure. Now the code works with all viewModels such as Person_LocationOview. With the full scheme classes, the code still crashes and I do not know why.
Now, all my view classes are implementing an own interface (IPartialEntityView).
In my reflection method to get the field names I'll check this inheritance and only then I will load "Addresses.FieldName(s)". If the property type is no default .NET type or does not inherit IPartialEntityView I will use the complete field "Adresses".
That works great.
Thanks for all.