有人对 ServiceStack Ormlite 中的 postgres jsonb 有疑问吗?

Anyone have problems with postgres jsonb in ServiceStack Ormlite?

今天我使用 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”。所有其他人都正确加载。

现在我已经改回标准文本列类型并且一切正常。

如果您不想在生成的 JSON 中包含 __type 信息,则不应使用 interfaces or late-bound objects in Data models

特别是在跨进程边界(例如数据库、缓存、网络)持久化时,我会考虑避免使用 OOP 对象图并考虑使用干净的具体 POCO 模型(它们在任何地方都有更可预测的行为)。

jsonb 将 json 对象存储为字典,因此对象中的键顺序 保留。坦率地说,我认为采用特定键顺序的应用程序有些问题,但它们确实存在。

如果您想保留键顺序(并保留重复键),您需要使用普通 json 类型。这会验证 json,但不会对其执行任何其他操作。缺点是它的索引和数据库内运算符更加有限。