反序列化具有不同属性名称的嵌套JSON

3

我有一个自定义的合同解析器,用于将我的模型中的属性名称解析为RESTful API调用返回的属性名称。以下是一个示例API调用:

{
    "record_id": "f461dc88-2a3c-428c-ad92-1d03477667cf",
    "company": "Palm Beach Photographics",
    "company_info": {
        "images": [
            "https://picsum.photos/200/300?image=719",
            "https://picsum.photos/200/300?image=653",
            "https://picsum.photos/200/300?image=965"
        ],
        "industries": [
            "Real Estate",
            "Photo/Film",
            "Utilities/Energy/Infrastructure",
            "Emergency Services"
        ],
        "location_state": "FL",
        "overview": "Per fusce luctus diam hac dictum posuere non interdum conubia eleifend, fusce suscipit purus aliquam porttitor amet fames nostra sapien potenti fusce, quisque felis quisque ante fringilla nulla rutrum porta at inceptos mi per mattis rhoncus id."
    }
}

我的模型如下:

public class Company
{
    public Guid Id { get; set; }

    public string Name { get; set; }

    public CompanyInfo Info { get; set; }
}

public class CompanyInfo
{
    public IEnumerable<Uri> Images { get; set; }

    public string State { get; set; }

    public IEnumerable<string> Industries { get; set; }

    public string Overview { get; set; }
}

public class CustomContractResolver : DefaultContractResolver
{

    private Dictionary<string, string> PropertyMappings { get; }

    public CustomContractResolver(Dictionary<string, string> propertyMappings)
    {
        PropertyMappings = propertyMappings;
    }

    protected override string ResolvePropertyName(string propertyName)
    {
        var resolved = PropertyMappings.TryGetValue(propertyName, out var resolvedName);
        return (resolved) ? resolvedName : base.ResolvePropertyName(propertyName);
    }
}

如何在不使用JsonProperty和其他标签的情况下,使嵌套的company_info正确绑定到我的模型中呢?当我使用JsonConvert反序列化对象时,我要传入以下属性映射:

private readonly Dictionary<string, string> _propertyMappings = new Dictionary<string, string>
    {
        {"Id", "record_id"},
        {"Name", "company"},
        {"Info.Images", "company_info.images"},
        {"Info.Industries", "company_info.industries"},
        {"Info.State", "company_info.location_state"},
        {"Info.Overview", "company_info.overview"}
    };

Id和Name正确绑定,但是Info中的任何内容都没有映射。

该映射器使用反射获取属性名称。您的注释当前没有映射到任何现有的属性。让成员对象的属性直接解析为成员对象。 - PepitoSh
抱歉,您是在建议我将公司信息的属性移动到公司中吗?能否请您举个例子或详细解释一下您的意思。 - uioporqwerty
2个回答

2
如果你不想改变任何属性名称以匹配Json属性,也不想使用JsonProperty,那么你可以将错误的属性映射修复为以下内容。
private static readonly Dictionary<string, string> _propertyMappings = new Dictionary<string, string>
    {
        {"Id", "record_id"},
        {"Name", "company"},
        {"Info", "company_info"},
        {"State", "location_state"}
    };

只需告诉Deserializer将名称映射到名称,无需在其中放置任何嵌套对象希望它可以解决您的问题。

啊,太好了。它起作用了。但我对解析器的工作原理很好奇。当合同解析器遇到公司信息时,我想它会开始将信息映射到公司信息下的所有属性。那么州是如何映射到位置_州呢? - uioporqwerty
我认为在嵌套类中,当它们尝试解析“location_state”时,它们与根类做的一样,会检查自定义映射中是否存在“location_state”,如果不存在,则使用相同的名称进行映射,但如果存在,则使用我们分配的特定名称进行映射。 - Asakuraa Ranger
2
请注意,这种方法打开了各种模糊性的大门,当底层对象发生任何变化时,调试可能会变得麻烦。 - PepitoSh
如果您为反序列化创建了自定义映射,并且更改了类而不更改映射,则每种方法都会使相同的调试繁琐。 - Asakuraa Ranger
那么我们如何避免这种歧义?在序列化时,我们如何处理类名? - ozziem
根据您的序列化器,使用JsonPropertyName或JsonProperty属性,假设类名是在类中引用的属性名称。有关详细信息,请参阅https://www.newtonsoft.com/json/help/html/jsonpropertyname.htm和https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-customize-properties?pivots=dotnet-6-0。 - Asakuraa Ranger

1
您要求的示例已经格式化如下:

public class Company
{
    public Guid Id { get; set; }

    public string Name { get; set; }

    public CompanyInfo Info { get; set; }

    public IEnumerable<Uri> Info_Images { 
      get {
         return Info.Images;
      }
      set {
         if (Info == null) {
            Info = new CompanyInfo();
         }
         Info.Images = value 
      }
    }
    // etc., with the other properties.
}

public class CompanyInfo
{
    public IEnumerable<Uri> Images { get; set; }

    public string State { get; set; }

    public IEnumerable<string> Industries { get; set; }

    public string Overview { get; set; }
}

而且映射可以如下进行:
private readonly Dictionary<string, string> _propertyMappings = new Dictionary<string, string>
    {
        {"Id", "record_id"},
        {"Name", "company"},
        {"Info_Images", "company_info.images"},
        {"Info_Industries", "company_info.industries"},
        {"Info_State", "company_info.location_state"},
        {"Info_Overview", "company_info.overview"}
    };

{"Info_Industries", "company_info.industries"} 不起作用,答案是错误的。 - ozziem

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接