Mapping object with properties names and values - c#

I have class
public class Foo
{
public string Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
}
I want to convert the object to a generic object
{
"properties": {
"id" : "1234",
"name": "John Doe",
"email" : "john.doe#mail.com"
}
}
I want to convert the class instance to the structure where the properties would be dynamic depending on the class. Is this possible with Automapper?

Seems you want to serialize/deserialize to/from JSON. In this case you can reference to Newtonsoft.Json and use the JsonConvert.SerializeObject/JsonConvert.DeserializeObject generic method which does not depend on any specific class:
Deserializing (From String to Class Instance):
var foo = JsonConvert.DeserializeObject<Foo>(jsonString);
Serializing (From Class Instance to String):
var stringValue = JsonConvert.SerializeObject(foo)
One More Point (Mapping)
Also you may want to decorate your class with some attributes to specify the mapping:
[DataContract]
public class Foo
{
[DataMember(Name = "id")]
public string Id {get;set;}
[DataMember(Name = "name")]
public string Name {get;set;}
[DataMember(Name = "email")]
public string Email {get;set;}
}

Partially AutoMapper cannot map to dictionary or ExpandoObject, so no.
The following solution was posted before I was aware that by mapping to an ExpandoObject Automapper will simply leave you with an empty object.
The simplest solution would be this I think (assuming you want an ExpandoObject as a result):
public ExpandoObject Map<TInput>(TInput inputObject)
{
dynamic result = new ExpandoObject();
result.properties = Mapper.DynamicMap<TInput, ExpandoObject>(inputObject);
return (ExpandoObject)result;
}
As far as I know you can't delegate all members as child properties to another field using automapper, but it's simple to do this yourself. AutoMapper is completely useless here.
edit: seems that automapper struggles with ExpandoObject... Actually it seems like AutoMapper cannot do this at all, so you're left with reflection.
You would then write a reflection object that can create or populate a dictionary with the objects properties.

Related

Use DataMember during deserialize but nut during serialize?

I'm having trouble understanding serialization of one of my objects.
Scenario:
I'm receiving data from a service which is in a given format. I want to take the data in as is. Due to naming conventions I have to use DataMember properties to match the incoming data to properly named class properties. I use System.Runtime.Serialization for this. Example:
[DataContract]
public class IncomingData
{
[DataMember(Name = "$Filename")]
public string Filename { get; set; }
}
This works fine and the data is mapped to the internal property name.
At some point I have to serialize this object again and I naively thought that it would serialize to the internal property name e.g.
{ "Filename":"C:\temp\lala.txt"}
however that is not true and the original propertyname "$Filename" is used instead. I assume this is because DataMember works both ways.
Is there an elegant way to have this object serialize to the propertynames and ignore DataMember? I tried if using a different serialization library works (JSON.NET) but it also seems to follow DataMember.
Do I have to wrap this object to another to acchieve?
Thanks for any hints!
blu
You could define an interface for keeping these objects in sync...
public interface IData
{
string Filename { get; set; }
}
// deserialize me.
[DataContract]
public class IncomingData : IData
{
[DataMember(Name = "$Filename")]
public string Filename { get; set; }
}
// serialize me.
public class Data : IData
{
public string Filename { get; set; }
}
...or you could use virtual properties and override them with the serialization attributes...
// serialize me.
class Data
{
public virtual string Filename { get; set; }
}
// deserialize me.
[DataContract]
class IncomingData : Data
{
[DataMember(Name = "$Filename")]
public override string Filename { get => base.Filename; set => base.Filename = value; }
}
...both of these methods would require the use of a mapper like AutoMapper to clone the IncomingData into the attribute-free Data class...
mapper.Map<IncomingData, Data>(user);
...so I appreciate this feels less than ideal.

Adding new property to .Net object

I have a WCF web service that is consumed in an MVC4 application that returns an object. I want to add another property to the object after it is loaded. Essentially I want a clone of the object plus my new property.
How would I do that?
Would it be best to deserialize to JSON, then add the new property and then serialize it into my new object with the extra property or is there another way to do it?
If you want to keep things simple, you can simply create your new Type including all properties of given object and your desired new property, then fill your new class and do what do you want with it.
Also consider reading Note part.
For complicated cases and large applications, you can consider solutions like what abatishchev mentioned in his answer.
class Foo
{
public int Id { get; set; }
public string Name { get; set; }
}
class FooViewModel
{
public FooViewModel()
{
}
public FooViewModel(Foo foo)
{
this.Id= foo.Id;
this.Name= foo.Name;
}
public int Id { get; set; }
public string Name { get; set; }
public string NewProperty{ get; set; }
}
And use it this way:
var foo = Service.GetFoo();
var fooViewModel= new FooViewModel(foo);
fooViewModel.NewProperty = "new value";
Note:
You can use a Foo instance in FooViewModel and all getters and setters act on that instance to keep thing synchronized.
Sometimes you can enhance the solution using inheritance from Foo, this way you don't need too create each properties again.
For complicated cases and large applications, you can consider solutions like what abatishchev mentioned in his answer.
I think what you're looking for is AutoMapper. You can map one object into another. Say, you have a DTO entity with X properties. Then you have a business logic entity with the same X properties + Y additional. AutoMapper will handle it easily.
class OrderDto
{
public int OrderId { get; set; }
}
class OrderViewModel
{
public int OrderId { get; set; }
public int DisplayOrder { get; set; }
}
Mapping:
var dto = new OrderDto { OrderId = 2 };
var vm = mapper.Map<OrderViewModel>(dto);
vm.DisplayOrder = 3;
Would it be best to deserialize to JSON, then add the new property and
then serialize it into my new object with the extra property or is
there another way to do it?
It's definitely would be easier and cost less efforts to use JSON.
But if you want more control over the generation process see that answer how to generate classes on the fly.

Serializing properties of derived type from base type collection with NewtonSoft Json.NET

Update: solved! It seems like Json.NET does include derived type properties by default, but they were not included because of an error in my code where the derived type was overwritten by a base type.
I am currently working on a project for school, and I stumbled upon a problem.
I need to serialize an object to Json, which I do using Newtonsoft Json.NET. The object I am trying to serialize has a List of objects of a certain base class, but the objects in that List are of derived types with their own unique properties.
Currently, only the properties of the base class are included in the resulting Json. If it's possible, I'd like the Json converter to detect of which derived class the objects in the collection are, and to serialize their unique properties.
Below some code as an example of what I'm doing.
Classes I use:
public class WrappingClass
{
public string Name { get; set; }
public List<BaseClass> MyCollection { get; set; }
}
public class BaseClass
{
public string MyProperty { get; set; }
}
public class DerivedClassA : BaseClass
{
public string AnotherPropertyA { get; set; }
}
public class DerivedClassB : BaseClass
{
public string AnotherPropertyB { get; set; }
}
Serializing some dummy objects:
WrappingClass wrapperObject = new WrappingClass
{
Name = "Test name",
MyCollection = new List<BaseClass>();
};
DerivedClassA derivedObjectA = new DerivedClassA
{
MyProperty = "Test my MyProperty A"
AnotherPropertyA = "Test AnotherPropertyA"
};
DerivedClassB derivedObjectB = new DerivedClassB
{
MyProperty = "Test my MyProperty B"
AnotherPropertyB = "Test AnotherPropertyB"
};
wrapperObject.MyCollection.Add(derivedObjectA);
wrapperObject.MyCollection.Add(derivedObjectB);
var myJson = JsonConvert.SerializeObject(wrapperObject);
The Json that would currently be generated:
{"Name":"Test name","MyCollection":[{"MyProperty":"Test my MyProperty A"}{"MyProperty":"Test my MyProperty B"}]}
The Json I want:
{"Name":"Test name","MyCollection":[{"MyProperty":"Test my MyProperty A","AnotherPropertyA":"Test AnotherPropertyA"},{"MyProperty":"Test my MyProperty B","AnotherPropertyB":"Test AnotherPropertyB"}]}
Any ideas? Thank you!
The default behavior of json.NET is to include all properties on derived types. The only reason you would not be getting them is if you have defined a [DataContract] on the base type which you have not extended to your derived types or if you have something like optin serialization ect.
Decorate the properties with Ignore attribute if you dont want them serialized like
public class DerivedClassA : BaseClass
{
[JsonIgnore]
public string AnotherPropertyA { get; set; }
}

Casting derived class to base class keeps knowledge of derived when using generics

I have a weird scenario that I can't seem to wrap my head around. I have the following base class:
public class Note
{
public Guid Id { get; set; }
public string SenderId { get; set; }
...
}
Which is then derived by the following class:
public class NoteAttachment : Note
{
public string FileType { get; set; }
public string MD5 { get; set; }
...
}
I use these classes to communicate with a server, through a generic wrapper:
public class DataRequest<T> : DataRequest
{
public T Data { get; set; }
}
public class DataRequest
{
public string SomeField { get; set; }
public string AnotherField { get; set; }
}
So I have a NoteAttachment sent to the method, but I need to wrap a Note object to send to the server. So I have the following extension method:
public static DataRequest<T> GetDataRequest<T>(this T data)
{
DataRequest<T> dataRequest = new DataRequest<T>
{
SomeField = "Some Value",
AnotherField = "AnotherValue",
Data = data
};
return dataRequest;
}
Now the problem. Calling the extension method in the following way works fine, however even though the DataRequest type is DataRequest<Note>, the Data field is of type NoteAttachment.
var noteAttachment = new NoteAttachment();
...
Note note = (Note)noteAttachment;
var dataRequest = note.GetDataRequest();
Debug.WriteLine(dataRequest.GetType()); //MyProject.DataRequest`1[MyProject.Note]
Debug.WriteLine(dataRequest.Data.GetType()); //MyProject.NoteAttachment <--WHY?!
What am I doing wrong?
You are mixing two things: run-time type of an object and compile type of a field.
Type of Data field is still Note. You can verify for yourself with reflection. For example, the following will print "Note":
Console.Write(
typeof(DataRequest<Note>).GetProperty("Data").PropertyType.Name);
The Type of the object that this field contains can be Note or any derived type. Assigning an object to the variable of a base class does not change its run-time class. And since GetType() returns the type of an object you get the actual derived type (NoteAttachment).
As #Alexi answered your first question, ill try the second question in the comment. Add a KnownType attribute to your note class like this:
[KnownType(typeof(NoteAttachment)]
public class Note

How do I remap names to object properties when deserializing, using Json.Net in C#

Case:
I receive a JSON string from third-party server, containing a list of objects.
e.g.
[{"foo": "bar", "someotherfield": "somevalue"}, {etc}, {etc}]
I have a C# class like,
public class MyObject
{
public string A { get; set; }
public string B { get; set; }
}
Now, I want to use JsonConvert.DeserializeObject, but so that it maps "foo" to A and so forth. How would I go about doing this?
You can use the JsonProperty attribute.
[JsonProperty("foo")]
public string A { get; set; }
You can use the JsonPropertyAttribute decorated on the property, giving it the name of the parameter it should find in the JSON message. You can also use a custom JsonConverter, if you do not wish to use an attribute.

Categories

Resources