Search code examples
c#servicestackservicestack-text

ServiceStack Serialize and Deserialize Dictionary with Objects


I have a very weird problem here pertaining to ServiceStack.Text's serializer.

Suppose I have two classes, one called Person and another called Address.

Person:

public class Person
{
    public string Name { get; set; }
    public Dictionary<string,object> ExtraParams { get; set; }
}

Address:

public class Address
{
    public string StreetName { get; set; }
}

In one of the methods I do this

var john = new Person 
         {
           Name: "John",
           ExtraParameters: new Dictionary<string, object>
            {
                { "AddressList", new List<Address>{
                     new Address{ StreetName : "Avenue 1" }
                  }
                }
            }
         };

I am using ServiceStack's ORMLite too. Now the problems comes when I try to retrieve the data from the database and cast it back to dictionary:

//save to database
var id = db.Save(john)

//retrieve it back
var retrieved = db.SingleById<Person>(id);

//try to access the Address List
var name = retrieved.Name; //this gives "John" 
var address = retrieved.ExtraParameters["AddressList"] as List<Address>; //gives null always , due to typecasting failed.

When I try to debug, the ExtraParameters is a Dictionary, with key named "AddressList", but the value is actually a string - "[{StreetName:"Avenue 1"}]"

Any ideas where have I done wrong? I have looked up and down on SO about typecasting on the objects and dictionaries, but none of them seemed to have the same issue as I do.

I have set the following configs:

JsConfig.ExcludeTypeInfo = true;
JsConfig.ConvertObjectTypesIntoStringDictionary = true;

Solution

  • While what Demiz said is true - that Inheritance in DTO is bad, I would really want to post a more accurate answer for the question just in case anyone really needs it.

    Set the following flags:

    JsConfig.ExcludeTypeInfo = false; //this is false by default
    JsConfig.ConvertObjectTypesIntoStringDictionary = true; //must set this to true
    

    For List of objects that happens to be serialized, you would need to deserialize it as a list of objects first and cast each one of it back to the original class:

    //save to database
    var id = db.Save(john);
    
    //retrieve it back
    var retrieved = db.SingleById<Person>(id);
    
    //try to access the Address List
    var name = retrieved.Name; //this gives "John" 
    //cast it to list of objects first
    var tempList = retrieved.ExtraParameters["AddressList"] as List<object>; 
    //cast each of the objects back to their original class;
    var address = tempList.Select(x=> x as Address); 
    

    Hope this one helps whoever needs it in the future.