【问题标题】:Deserialize list of JSON strings to find the correct model反序列化 JSON 字符串列表以找到正确的模型
【发布时间】:2019-10-16 12:46:10
【问题描述】:

这很烦人,我只需要运行此代码一次。之后,所有内容都将被删除(这是迁移代码)

我有一个 List<string> 的 JSON 字符串。它们包含各种不同格式的 JSON 对象,如下所示:

{
    "id": 123
}
{
    "id": "7521b497-abb7-46b8-bddc-177a6fd9f974",
    "folderId": 123
}
{
    "folderId": 123
}

等等。我需要获取123,它可以在属性idfolderId 中。如果我只是这样做:

class IdModel {
    public int Id { get; set; }
}

//inside a function
var model = JsonConvert.DeserializeObject<IdModel>(json);

当它到达第二个 JSON 时它会失败,因为id 是一个 GUID。相反,它需要寻找FolderId,这意味着我可以这样做:

class IdModel {
    public int Id { get; set; }
}

class FolderIdModel {
    public int FolderId { get; set; }
}

//inside a function
int folderId;

try {
    var model = JsonConvert.DeserializeObject<FolderIdModel>(json);
    folderId = model.FolderId;
} catch {
    var model = JsonConvert.DeserializeObject<IdModel>(json);
    folderId = model.Id;
}

在这种情况下这“很好”,但我可能有 10 个不同的 JSON 对象,它们看起来都不同。 FolderId &gt; Id,因为我一直都知道 FolderId 是正确的,除非它没有 FolderId,在这种情况下它可能有一个 Id(如果 FolderId 或 Id 都不正确,应该会爆炸)。

我的问题是:有没有一种聪明的方法可以反序列化为不同的模型,而不需要查看 JSON?请记住,Id 既可以是 GUID,也可以是整数,具体取决于 JSON 对象。

我知道这真的很糟糕,我很抱歉。

【问题讨论】:

  • 反序列化为dynamic,你可以随意访问。这对于生产代码来说不是很健壮,但对于一次性使用来说还不错。
  • 为什么你根本不声明财产 public int Id { get;放; } 作为公共字符串 ID { 获取;放; }
  • 我会反序列化为 JObject(如果使用 Newtonsoft 的包)而不是 dynamic,然后检查它是否具有所需的数据。

标签: c# .net json json.net


【解决方案1】:

是的,您可以使用dynamic 类型,它将匹配您的Json 对象的结果,然后验证值类型是Guid 还是int,如下所示:

int folderId;
var model = JsonConvert.DeserializeObject<dynamic>(json);
folderId = model.id != null && model.id is int ? model.id : model.folderId;

如果有更多可能的结果,您可以打破这个三元运算符并单独验证它们。

【讨论】:

    【解决方案2】:

    我只是用同一个类反序列化它们,然后根据属性值解析它们。例如:

    public class IdModel
    {
        public string Id { get; set; }
        public string FolderId { get; set; }
    
        public int Value
        {
            get
            {
                if (int.TryParse(Id, out int value))
                {
                    return value;
                }
                else if (int.TryParse(FolderId, out value))
                {
                    return value;
                }
                else
                {
                    throw new Exception("This model has no valid id");
                }
            }
        }
    }
    

    用法:

    string json1 = "{\"id\": 123}";
    string json2 = "{\"id\": \"7521b497-abb7-46b8-bddc-177a6fd9f974\",\"folderId\": 123}";
    string json3 = "{\"folderId\": 123}";
    
    IdModel model1 = JsonConvert.DeserializeObject<IdModel>(json1); // model1.Value = 123
    IdModel model2 = JsonConvert.DeserializeObject<IdModel>(json2); // model2.Value = 123
    IdModel model3 = JsonConvert.DeserializeObject<IdModel>(json3); // model3.Value = 123
    

    【讨论】:

    • 实际上似乎是一个可靠的计划
    【解决方案3】:

    我会在模型中添加一个额外的属性来获取真实的 id(FolderId 或 Id,取决于设置正确)。 模型如下所示:

    class Model
            {
                public string Id { get; set; }
                public int? FolderId { get; set; }
                public int RealFolderId
                {
                    get
                    {
                        if (FolderId != null)
                        {
                            return FolderId.Value;
                        }
                        int id;
                        if (int.TryParse(Id, out id))
                        {
                            return id;
                        }
                        throw new Exception("This explodes");
                    }
                }
            }
    

    id 被序列化为字符串,因此当 Id 为 Guidint 时,它都不会中断。当 FolderId 和 Id 都具有“不正确的值”时,将抛出 Exception;没有一个是int

    其余的代码将非常简单:

    var deserialized = JsonConvert.DeserializeObject<Model>(json);
    int folderId = deserialized.RealFolderId;
    

    【讨论】:

      【解决方案4】:

      您可以尝试使用DeserializeAnonymousType 方法,类似的东西

      var responseObject = JsonConvert.DeserializeAnonymousType(json, new { id = "" });
      
      

      将其转换为所需类型(intGuid)或仅使用 object 类型

      【讨论】:

      • 那我该怎么处理 FolderId 呢?
      • 您可以为folderId 引入匿名类型的附加字段并检查生成的对象
      猜你喜欢
      • 1970-01-01
      • 2023-03-23
      • 2020-10-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-22
      • 1970-01-01
      相关资源
      最近更新 更多