今天我使用ServiceStack Ormlite在postgres中使用jsonb数据类型。基本模型具有复杂的类型属性,其本身包含接口对象的字典(下面的伪代码)。
通常,ServiceStack通过向json添加“__type”标识符来处理此问题。它做得正确。但是,对于其中一个字典项,“__type”标识符在属性下面第二个列出,这导致从postgres检索项目时返回一个空对象。更有趣的是,就我所知,序列化程序首先列出了“__type”,但是一旦它被存储在postgres中,它就被重新排序。 jsonb数据类型是否重新排序json属性?
模型的伪代码(在实际代码中更广泛)
public class StrategyContainer
{
public Dictionary<int, List<IStrategy>> SetOfStrategies { get; set; }
}
public interface IStrategy
{
int Health { get; set; }
string Name { get; set; }
}
public interface IAttack : IStrategy
{
int Strength { get; set; }
}
public abstract class AbstractStrategy : IStrategy
{
public int Health { get; set; }
public string Name { get; set; }
}
public class Attack : AbstractStrategy, IAttack
{
public int Strength { get; set; }
}
以下是从postgres jsonb列中检索时json的出现方式。
{
"SetOfStrategies": {
"1": [{
"__type": "Test.Attack, Test",
"Strength": 10,
"Health": 5,
"Name": "Testing"
},
{
"Strength": 20,
"__type": "Test.Attack, Test",
"Health": 10,
"Name": "Testing2"
}]
}
注意:字典列表中还有许多其他项目。其中只有一个人误以为“__type”。所有其他正确加载。
现在我已经回到了标准的文本列类型,一切正常。
答案 0 :(得分:1)
如果您不想在生成的JSON中使用 __ type 信息,则不应使用interfaces or late-bound objects in Data models。
特别是当跨越进程边界(例如数据库,缓存,网络)持久存在时,我会考虑避免使用OOP对象图,而是使用干净的具体POCO模型(在任何地方都有更可预测的行为)。
答案 1 :(得分:1)
jsonb
将json对象存储为字典,因此对象中的键顺序不保留。坦率地说,我认为假定特定密钥排序的应用程序有些破坏,但它们确实存在。
如果要保留密钥排序(并保留重复密钥),则需要使用普通json
类型。这会验证json,但不会对其进行任何其他操作。缺点是它有更多有限的索引和数据库内运营商。