ServiceStack ORMLite does not deserialize my class from Postgresql.
Keeping the objects on cache solves, but it can't load them back (saving is ok).
Below is a code that reproduces the problem.
void Main()
{
var inv = new Inventory();
inv.Items.Add(new Item{Id=1,CreatedAt=DateTime.Now, Key="potion10", Descriptions=new Dictionary<int, string>{{1,"Poção que recupera um pouco de vida."},{2,"Potion that restores a little of health."}}, HealthModifier=10,IsUseable=true, Names=new Dictionary<int, string>{{1,"Poção Leve"},{2,"Minor Potion"}}, UpdatedAt=DateTime.Now}, 2);
var invJson = inv.ToJson().To<Inventory>(); // can't deserialize
var invJsv = inv.ToJsv().To<Inventory>(); // same problem
}
public class Item
{
public Item()
{
Names = new Dictionary<int, string>();
Descriptions = new Dictionary<int, string>();
}
public long Id { get; set; }
public string Key { get; set; }
public Dictionary<int, string> Names { get; set; }
public Dictionary<int, string> Descriptions { get; set; }
public int HealthModifier { get; set; }
public bool IsUseable { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime UpdatedAt { get; set; }
}
public class Inventory
{
public Inventory()
{
Items = new Dictionary<Item, int>();
}
public Dictionary<Item, int> Items { get; set; }
}
The JSON on Postgresql is the same from the code above.
{
"Items":{
"{"Id":1,
"Key":"potion10",
"Names":{
"1":"Poção Leve",
"2":"Minor Potion"
},
"Descriptions":{
"1":"Poção que recupera um pouco de vida.",
"2":"Potion that restores a little of health."
},
"HealthModifier":10,
"IsUseable":true,
"CreatedAt":"\/Date(1430743156138-0300)\/",
"UpdatedAt":"\/Date(1430743156139-0300)\/"
}:2
}
}
The problem is that your class Inventory
has a dictionary keyed by a complex class:
public Dictionary<Item, int> Items { get; set; }
However, according to the ServiceStack.Text documentation
Any IDictionary is serialized into a standard JSON object, i.e:
{"A":1,"B":2,"C":3,"D":4}
Unfortunately your Item
class cannot be represented as a simple string thus cannot be used as a JSON property name.
What you could do is to serialize your items as an array of key-value pairs. Since the ServiceStack Text serializers support [DataMember]
aliases and also support ignoring of data members, you can do the following:
[DataContract]
public class Inventory
{
public Inventory()
{
Items = new Dictionary<Item, int>();
}
[IgnoreDataMember]
public Dictionary<Item, int> Items { get; set; }
[DataMember(Name = "Items")]
public KeyValuePair<Item, int> [] ItemArray
{
get
{
return Items == null ? null : Items.ToArray();
}
set
{
(Items ?? (Items = new Dictionary<Item, int>())).Clear();
if (value != null)
foreach (var pair in value)
Items[pair.Key] = pair.Value;
}
}
}
This will serialize and deserialize valid JSON that should look something like this:
{ "Items": [ { "Key": { "Id": 1, "Key": "potion10", "Names": { "1": "Poção Leve", "2": "Minor Potion" }, "Descriptions": { "1": "Poção que recupera um pouco de vida.", "2": "Potion that restores a little of health." }, "HealthModifier": 10, "IsUseable": true, "CreatedAt": "2015-05-04T02:07:10.7216263-04:00", "UpdatedAt": "2015-05-04T02:07:10.7216263-04:00" }, "Value": 2 } ] }
However, you mentioned that your JSON was coming from Postgresql. What does that JSON look like? You may need to adapt your serialization or classes to what you are actually receiving.