如何获取特定JSON值的架构?

时间:2019-07-03 08:53:27

标签: json json.net jsonschema json-schema-validator

众所周知,用oop语言,我们可以知道实例的类型和实例的属性的类型。

我认为JSON值就像JSON模式的实例一样。那么,有什么解决方案可以获取每个JSON值的子模式吗?

例如,我手头有JSON模式和JSON实例,如下所示:

{
    'definitions': {
        'img': {
            'type': 'object',
            'properties': {
                'url': {
                    'type': 'string'
                }
            }
        }
    },
    'type': 'object',
    'properties': {
        'name': {
            'type':'string'
        },
        'avatar': {
            '$ref': '#/definitions/img'
        }
    }
}

还有JSON实例:

var json =
{
  'name': 'James',
  'avatar': {'url':'http://xxxx.jpg'}
}

当我以编程方式访问json.avatar时,如何获得化身的类型为“ img”?

顺便说一句,我正在使用JSON.Net Schema

1 个答案:

答案 0 :(得分:0)

尝试解决此问题时,重要的一件事是Jschema在何处以及如何存储定义,您可以像在JObject中一样遍历模式。

因此,假设您是这样加载架构的(使用Newtonsoft):

var schema = JSchema.Parse(@"{
                    'definitions': {
                        'img': {
                            'type': 'object',
                            'properties': {
                                'url': {
                                    'type': 'string'
                                }
                            }
                        }
                    },
                    'type': 'object',
                    'properties': {
                        'name': {
                            'type':'string'
                        },
                        'avatar': {
                            '$ref': '#/definitions/img'
                        }
                    }
                }");

访问架构的 avatar 属性时,您实际上会获得已被定义替换的链接(因为Jschema在解析过程中正在替换它)。但是定义本身并没有丢失,而是存储在schema.ExtensionData["definitions"]中-一开始让我感到惊讶-您可以访问这些定义,例如标准JObjects。

在某些条件下(例如,使用 url 令牌具有单个定义),您可以访问实际的定义类型:

        var avatarKey = schema.Properties["avatar"].Properties.Keys.Single(); //'url'
        var definitions = schema.ExtensionData["definitions"]; 

然后获取包含 url 的定义并获取根名称(在您的方案中为 img ):

        var matching = definitions.SelectTokens($"..{avatarKey}");
        var avatarDefinition = matching.Single().Root;
        var avatarType = (avatarDefinition.First() as JProperty).Name; //'img'

这不是每种模式的通用解决方案,但是您可以基于此解决方案将其调整为更复杂的需求。