You need to enable JavaScript to run this app. C#中Newtonsoft.Json反序列化动态JSON为ExpandoObject后如何判断属性是否存在
优惠活动
大模型
产品
解决方案
定价
更多

C#中Newtonsoft.Json反序列化动态JSON为ExpandoObject后如何判断属性是否存在

问题根因

你之前的判断方法未生效,核心原因是Newtonsoft.Json默认反序列化ExpandoObject时,嵌套的对象不会被解析为ExpandoObject类型,而是JObject类型,因此针对ExpandoObject编写的类型强转判断逻辑自然无法运行。

解决方案

方案1:直接适配默认JObject类型(无需修改反序列化配置)

不需要调整反序列化逻辑,直接使用JObject的特性判断属性是否存在,同时可以直接用LINQ完成过滤:

// 示例代码,包含LINQ查询实现
var PPL = new List<string> { "city", "farm", "hamlet", "isolated_dwelling", "neighbourhood", "quarter", "suburb", "town", "village" };

JsonSerializer serializer = new JsonSerializer();

using (FileStream s = File.Open(jsonFile, FileMode.Open))
using (StreamReader sr = new StreamReader(s, Encoding.UTF8))
using (JsonReader reader = new JsonTextReader(sr))
{
    while (reader.Read())
    {
        if (reader.TokenType == JsonToken.StartObject)
        {
            dynamic jsonFeatures = serializer.Deserialize<ExpandoObject>(reader);
            // LINQ一步过滤出符合要求的条目
            var targetItems = ((IEnumerable<dynamic>)jsonFeatures.features)
                .Where(item => item.place != null) // 判断place属性存在且非空
                .Where(item => PPL.Contains((string)item.place, StringComparer.OrdinalIgnoreCase));

            foreach (var item in targetItems)
            {
                var osm_id = item.properties.osm_id ?? string.Empty;
                string name = item.properties.name ?? string.Empty;
                string is_in = item.is_in ?? string.Empty;
                string Place = item.place ?? string.Empty;
                string geom = JsonConvert.SerializeObject(item.geometry);
                
                Console.WriteLine("name: {0} is_in: {1} Place: {2} geom: {3} ", name, is_in, Place, geom);
            }
        }
    }
}

注意:如果你的place属性实际存放在properties节点下(和osm_id、name同级),将判断条件改为item.properties.place != null即可。

方案2:配置反序列化规则,嵌套对象统一为ExpandoObject

如果你需要所有嵌套对象都按照ExpandoObject处理,只需要给序列化器新增ExpandoObjectConverter转换器,你之前写的HasAttr方法就可以正常运行:

var PPL = new List<string> { "city", "farm", "hamlet", "isolated_dwelling", "neighbourhood", "quarter", "suburb", "town", "village" };

JsonSerializer serializer = new JsonSerializer();
// 新增转换器,让嵌套对象也反序列化为ExpandoObject
serializer.Converters.Add(new ExpandoObjectConverter());

using (FileStream s = File.Open(jsonFile, FileMode.Open))
using (StreamReader sr = new StreamReader(s, Encoding.UTF8))
using (JsonReader reader = new JsonTextReader(sr))
{
    while (reader.Read())
    {
        if (reader.TokenType == JsonToken.StartObject)
        {
            dynamic jsonFeatures = serializer.Deserialize<ExpandoObject>(reader);
            foreach (var item in jsonFeatures.features)
            {
                // 你的原有判断方法现在可以正常生效
                if(HasAttr((ExpandoObject)item, "place"))
                {
                    var osm_id = item.properties.osm_id ?? string.Empty;
                    string name = item.properties.name ?? string.Empty;
                    string is_in = item.is_in ?? string.Empty;
                    string Place = item.place ?? string.Empty;
                    string geom = JsonConvert.SerializeObject(item.geometry);
                    bool IsPPL = PPL.Contains(Place, StringComparer.OrdinalIgnoreCase);

                    if (IsPPL)
                    {
                        Console.WriteLine("name: {0} is_in: {1} Place: {2} geom: {3} ", name, is_in, Place, geom);
                    }
                }
            }
        }
    }
}

private static bool HasAttr(ExpandoObject expando, string key)
{
    return ((IDictionary<string, Object>)expando).ContainsKey(key);
}

LINQ查询说明

两种方案都支持用LINQ完成属性存在判断+值匹配的过滤逻辑,不需要手动写if嵌套,代码更简洁。

内容的提问来源于stack exchange,提问作者Holly

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.18 00:24:03