反序列化 JSON 字符串列表以查找正确的模型



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

我有一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 > Id,因为我总是知道 FolderId 是正确的,除非它没有 FolderId,在这种情况下它可能有一个 ID(如果 FolderId 或 Id 都不正确,应该爆炸(。

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

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

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

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

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

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

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

我会向模型添加一个额外的属性,该属性获取实际 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 是Guid时它既不会中断,也不会在它是int时中断。当文件夹 ID 和 ID 都有"不正确的值"时,将抛出Exception;没有一个是int.

其余代码将非常简单:

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

你可以尝试使用DeserializeAnonymousType方法,类似这样

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

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

最新更新