I have a couple of classes that look something like this:
public class Address
{
public string Country { get; set; }
public string Zip { get; set; }
public string State { get; set; }
public string City { get; set; }
public string Street { get; set; }
}
public class Order
{
public Address FromAddress { get; set; }
public Address ToAddress { get; set; }
public decimal Amount { get; set; }
...
}
I'm using Newtonsoft.JSON to serialize/deserialize those objects to JSON, but I have some rather specific requirements for how serializing should work.
For one, properties should all be snake case. This was easy enough using a SnakeCaseNamingStrategy with a contract resolver. However, I also want to bring the properties from the addresses up to the top level and have them renamed to append from or to to them. Basically:
{
"from_country": "US",
...
"to_country": "US",
...
"amount": "10.00"
}
I want to do all this without littering my classes with attributes and ideally without creating wrapper classes. I've been looking into the creation of custom ContractResolvers as well as custom JsonWriters, but I'm unable to figure out which or which combination of the two I need to achieve my desired format.
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.
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 am a bit stuck, hoping for guidance. I have 2 tables, Header and Details. However, the details is a bit different than most, and allows for a way to dynamically store data.: Yes, I am aware that I can create a table storing the details in the standard fashion, but the nature of the app needs to be more dynamic on the database side. I also realize I will have to modify the DTOs for different incarnations of the app, but this model is what I need to accomplish.
public class Header
{
public int Id { get; set; }
public string HeaderName { get; set; }
public ICollection<Detail> Details { get; set; }
}
public class Detail
{
public int Id { get; set; }
public int HeaderId { get; set; }
public string FieldName { get; set; }
public string FieldProperty { get; set; }
}
I want to use the following DTOs:
public class DataForDisplayDto
{
public int Id { get; set; }
public string HeaderName { get; set; }
public string TaskToPerform { get; set; }
public string Location { get; set; }
}
public class DataForCreationDto
{
public string HeaderName { get; set; }
public string TaskToPerform { get; set; }
public string Location { get; set; }
}
The data would be stored in the details in this fashion:
{
"FieldName": "tasktoperform",
"FieldProperty": "Thing to Do"
},
{
"FieldName": "location",
"FieldProperty": "Over there"
}
I am trying to use the Automapper to make it so I can read and write to the database using the DTOs, but I think I may be trying something it can't do.
Is there an article or something that anyone knows about that can point me in the direction to go? Or even the right keywords to search online for it. Is it even possible?
I suppose if it is not possible, I will have to do things a bit more manually, which is the last option, I am just hoping to do this with Automapper.
Thanks!
How about deriving your DTO from a base class that uses reflection to generate a mapping, and cache that mapping.
This way your DTO need only inherit a base class.
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.
Rather new to OOP..
I am gonna build a number of small applications that will support our main business.
These apps:
-Will need some common data classes
-The above classes may change in the future as far as properties are concerned (will add properties when ERP versions advance).
For example i have a class:
public class Lot
{
public string SSCC { get; set; }
public InventoryItem Item { get; set; }
public string DescriptionLocalLot { get; set; }
public string DescriptionEnglishLot { get; set; }
public DateTime ProductionDate { get; set; }
public string Shift { get; set; }
public string WorkOrder { get; set; }
public string ProductionLine { get; set; }
public string BarcodeEAN14 { get; set; }
public decimal Boxes { get; set; }
public decimal Units { get; set; }
public decimal Pieces { get; set; }
public DateTime LastUpdated { get; set; }
public string LastUser { get; set; }
public Warehouse LastWarehouse { get; set; }
public string ProductionLot { get; set; }
public string PalletSequence { get; set; }
}
The above class will be used by almost all applications (Windows forms or ASP pages). Ihave put this definition in a separate file called CommonClasses.
Should i define these classes as Abstract or Interfaces better? In most cases these classes will not include methods.
A class should describe all of an object's properties as well as methods that can act upon it. Not all are going to be used at once; but they are provided so that all the behavior is understood and state of an object can be tracked.
The class described in your code seems like a candidate for a concrete class. It provides a set of properties that are stored in memory and act in relation to one object. If you require additional functionality at a later point, you can extend the class to provide this.
If however, each instance of the class requires different implementation; then you should consider abstract class, or perhaps interface.
You should use concrete classes in your case if the change is common for all applications which are using these classes.