首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >我需要Newtonsoft JSON反序列化来跳过给定字典JSON中的条目

我需要Newtonsoft JSON反序列化来跳过给定字典JSON中的条目
EN

Stack Overflow用户
提问于 2020-03-08 20:50:01
回答 2查看 192关注 0票数 0

我将这个类作为JSON模式(这是正确的术语吗?):

代码语言:javascript
复制
class BasicInfoDatabase : Dictionary<string, BasicInfo>,
    IDictionary<string, BasicInfo>, 
    ICollection<KeyValuePair<string, BasicInfo>>, 
    IDictionary, 
    ICollection,
    IReadOnlyDictionary<string, BasicInfo>, 
    IReadOnlyCollection<KeyValuePair<string, BasicInfo>>,
    IEnumerable<KeyValuePair<string, BasicInfo>>, 
    IEnumerable, 
    ISerializable, 
    IDeserializationCallback 
{ }

注意:这里指定了Dictionary_的所有接口,以解决不相关的错误。否则,我将忽略它们。

输入JSON字符串中有一个未格式化为BasicInfo对象的条目。在反序列化输入字符串时,我想忽略这个特定的条目。以下是我用于此用途的代码:

代码语言:javascript
复制
private static bool HandleInfoReceipt( string jsonStr, out BasicInfoDatabase infoDb ) {
    infoDb = new BasicInfoDatabase();

    JObject respJson = JObject.Parse( jsonStr );
    if( respJson.Count == 0 ) {
        return false;
    }

    infoDb = respJson.ToObject<BasicInfoDatabase>();
    if( infoDb == null ) {
        throw new NullReferenceException( "No info found" );
    }

    return true;
}

我怎么跳过那个条目?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-03-10 00:05:00

JObject中筛选出属性非常简单。如何做到这一点取决于您对JSON的了解和不了解的内容。

例如,假设您的BasicInfo类定义如下:

代码语言:javascript
复制
class BasicInfo
{ 
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Amount { get; set; }
}

您的JSON如下所示:

代码语言:javascript
复制
{
  "good": {
    "Id": 1,
    "Name": "Foo",
    "Amount": 14.95
  },
  "acceptable": {
    "Id": 2,
    "Name": "Bar"
  },
  "suspect": {
    "Id": 3,
    "Hmm": "Blah"
  },
  "bad": {
    "Foo": "Bar",
    "Baz": "Quux"
  },
  "ugly": "total garbage"
}

如果您知道导致问题的特定键,您可以创建一个简单的扩展方法来筛选出这些键,如下所示:

代码语言:javascript
复制
public static void FilterOutUnwantedProperties(this JObject jo, params string[] keys)
{
    var unwantedProperties = jo.Properties().Where(jp => keys.Contains(jp.Name)).ToList();

    foreach (JProperty prop in unwantedProperties)
    {
        prop.Remove();
    }
}

然后,从您的HandleInfoReceipt方法调用它,如下所示:

代码语言:javascript
复制
respJson.FilterOutUnwantedProperties("bad", "ugly");

小提琴:https://dotnetfiddle.net/TfH6Fr

另一方面,也许你不提前知道键,或者它们是动态的。也许更好的方法是让扩展方法检查JObject中的每个属性值实际上是一个对象本身,并检查子对象属性的名称,以确保至少有一个属性(或所有属性?)匹配您想要的项目类型。看起来可能是这样的:

代码语言:javascript
复制
public static void FilterOutPropertiesThatAreNotCompatibleWith<TItem>(this JObject jo, BindingFlags flags=BindingFlags.Public|BindingFlags.Instance)
{
    var knownItemPropertyNames = 
        typeof(TItem).GetProperties(flags)
                     .Select(p => p.Name);
    var knownItemFieldNames = 
        typeof(TItem).GetFields(flags)
                     .Select(p => p.Name);
    var knownItemMemberNames = new HashSet<string>(knownItemPropertyNames);
    knownItemMemberNames.UnionWith(knownItemFieldNames);

    var unwantedProperties = 
        jo.Properties()
          .Where(jp => jp.Value.Type != JTokenType.Object ||
                       !jp.Value.Children<JProperty>()
                                .Any(cp => knownItemMemberNames.Contains(cp.Name)))
          .ToList();

    foreach (JProperty prop in unwantedProperties)
    {
        prop.Remove();
    }
}

你可以这样称呼这个版本:

代码语言:javascript
复制
respJson.FilterOutPropertiesThatAreNotCompatibleWith<BasicInfo>();

小提琴:https://dotnetfiddle.net/WsDmCE

票数 0
EN

Stack Overflow用户

发布于 2020-03-08 22:18:44

可能是这样的:

代码语言:javascript
复制
 var result = new BasicInfoDatabase();
 var jObject = JObject.Parse( jsonStr );
 foreach (var kvp in jObject )
 {
     if(kvp.Key != "<property-you-want-to-skip>")
     {
         result.Add(kvp.Key, kvp.Value.ToObject<BasicInfo>());
     }  
 }

编辑

更像是这样:

代码语言:javascript
复制
kvp.Value.ToObject<BasicInfo>();
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60591938

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档