使用C#从Azure Storage的JSON文件中提取sqlViewDefinition值
C#提取CDM文件中sqlViewDefinition节点实现方案
CDM格式的JSON结构嵌套层级不固定,手动按固定路径遍历或者逐层查找很容易因为结构变动匹配失败,以下是两种可直接落地的实现方式,基于你已经用Newtonsoft.Json解析得到JObject对象的前提:
方法1:JSONPath递归匹配(推荐,代码量最少)
Newtonsoft.Json原生支持JSONPath语法,用递归通配符可以无视所有嵌套层级直接定位目标节点,不需要手动写每层节点名:
// 递归查找全文档中第一个名为sqlViewDefinition的节点 JToken viewDefToken = parsedCdmJObject.SelectToken("$..sqlViewDefinition"); if (viewDefToken != null) { // 读取节点值即为目标SQL视图定义语句 string sqlViewText = viewDefToken.Value<string>(); }
如果单个CDM文件包含多个实体、对应多个sqlViewDefinition节点,把SelectToken替换为SelectTokens即可,返回值是可遍历的IEnumerable<JToken>集合,能拿到所有匹配的视图定义。
方法2:自定义递归查找(适配特殊过滤需求)
如果需要在查找时增加额外判断逻辑(比如仅提取指定实体名下的视图定义),可以实现通用递归查找方法:
/// <summary> /// 递归查找JSON中指定名称的节点值 /// </summary> /// <param name="currentToken">当前遍历的JSON节点</param> /// <param name="targetPropertyName">目标节点名</param> /// <returns>匹配到的节点值,未匹配返回null</returns> private static JToken FindTargetProperty(JToken currentToken, string targetPropertyName) { if (currentToken == null) return null; if (currentToken is JProperty prop && prop.Name == targetPropertyName) { return prop.Value; } foreach (var childToken in currentToken.Children()) { var matchResult = FindTargetProperty(childToken, targetPropertyName); if (matchResult != null) return matchResult; } return null; } // 调用示例 JToken viewDefToken = FindTargetProperty(parsedCdmJObject, "sqlViewDefinition"); if (viewDefToken != null) { string sqlViewText = viewDefToken.Value<string>(); }
注意事项
- 不要硬编码嵌套路径:类似
jObj["definitions"][0]["sqlViewDefinition"]的写法兼容性极差,只要CDM版本升级、节点多了一层命名空间包裹、或者实体数组顺序变动就会直接返回null - 留意命名空间前缀:部分版本CDM生成的JSON节点名会带命名空间前缀,比如
cdm:sqlViewDefinition,如果上述方法没匹配到,可以先遍历输出一层属性名确认,这种场景把JSONPath语句改为$..*[?(@pname =~ /sqlViewDefinition$/i)]即可忽略前缀、大小写做模糊匹配 - Blob下载时显式指定UTF8编码,避免SQL内容含特殊字符、中文时出现乱码导致解析失败,下载代码参考:
var blob = containerClient.GetBlobClient(targetBlobPath); using var readStream = await blob.OpenReadAsync(); using var streamReader = new StreamReader(readStream, Encoding.UTF8); string cdmJsonContent = await streamReader.ReadToEndAsync(); JObject parsedCdmJObject = JObject.Parse(cdmJsonContent);
内容的提问来源于stack exchange,提问作者Lonely Planeteer
相关产品推荐
相关产品推荐

