CozyAzure
CozyAzure

Reputation: 8468

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;

Upvotes: 2

Views: 1549

Answers (2)

CozyAzure
CozyAzure

Reputation: 8468

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.

Upvotes: 1

mythz
mythz

Reputation: 143319

Firstly storing object is a bad idea for serialization and I'd strongly avoid using it.

Next you're breaking serialization of object when you set:

JsConfig.ExcludeTypeInfo = true;

ServiceStack only adds the type info when it needs it, and this configuration prevents it from serializing the Type info in the JSON payload which is the only thing telling ServiceStack what to deserialize it back into which it needs because you're using a late-bound objects Type where ServiceStack can't know what the type is otherwise.

Upvotes: 2

Related Questions