json - 将 JSON 反序列化为扁平化类

标签 json json.net deserialization

我在这里发现了同样的问题...

Deserializing nested JSON structure to a flattened class with Json.NET using annotations

...但没有正确的答案。 最好的建议之一是将嵌套对象包装在一个新类中,但这种方法引入了另一个问题:乐高名称。在我的示例中,此类的最逻辑名称与父类和当然不可能。我的例子很简单,我只是想消除父类中的“语言”属性。有人可以帮我做吗?

using Newtonsoft.Json;

public partial class NamedType
{
    public string Name { get; set; }
}

public class Proficiency
{
    public string Level { get; set; }

    public string Name { get; set; }
}

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

    public string Name { get; set; }

    //public Language Language { get; set; } //Compiler error
    //public Language Value { get; set; } //Not correct
    //public NamedType Language { get; set; } //Compiler error
    //public NamedType Value { get; set; } //Ugly, isn't?

    public Proficiency Proficiency { get; set; }
}

List<Language> languageList = JsonConvert.DeserializeObject<List<Language>>(json);

json 示例:

{
    "languages": [
        {
            "id": 1,
            "language": { "name": "Spanish" },
            "proficiency": {
                "level": "native_or_bilingual",
                "name": "Native or bilingual proficiency"
            }
        },
        {
            "id": 2,
            "language": { "name": "English" },
            "proficiency": {
                "level": "full_professional",
                "name": "Full professional proficiency"
            }
        },
        {
            "id": 3,
            "language": { "name": "Japanese" },
            "proficiency": {
                "level": "elementary",
                "name": "Elementary proficiency"
            }
        }
    ]
}

最佳答案

如果 JSON 属性名称与 C# 命名约定冲突,您可以在序列化期间使用 DataMemberJsonProperty 注释来替换不同的名称。

例如,以下代码适用于 DataContractJsonSerializer 和 Json.NET:

[DataContract]
public class Language
{
    [DataContract]
    class NamedType
    {
        [DataMember]
        public string name { get; set; }
    }

    [DataContract]
    class ProficiencyType
    {
        [DataMember]
        public string level { get; set; }
        [DataMember]
        public string name { get; set; }
    }

    [DataMember(Name="id")]
    public int Id { get; set; }

    [IgnoreDataMember] // Do not serialize this property
    public string Name { get; set; }

    [IgnoreDataMember]
    public string ProficiencyLevel { get; set; }

    [IgnoreDataMember]
    public string ProficiencyName { get; set; }

    [DataMember(Name="language")] // serialize this nested class property with name "language"
    [JsonProperty(ObjectCreationHandling=ObjectCreationHandling.Replace)] // When deserializing, always create a fresh instance instead of reusing the proxy class.
    NamedType LanguageName
    {
        get
        {
            return new NamedType { name = Name };
        }
        set
        {
            Name = (value == null ? null : value.name);
        }
    }

    [DataMember(Name = "proficiency")]
    [JsonProperty(ObjectCreationHandling = ObjectCreationHandling.Replace)]
    ProficiencyType Proficiency
    {
        get
        {
            return new ProficiencyType { level = ProficiencyLevel, name = ProficiencyName };
        }
        set
        {
            ProficiencyLevel = (value == null ? null : value.level);
            ProficiencyName = (value == null ? null : value.name);
        }
    }
}

如果您发现 DataContract 属性的选择加入性质很麻烦,并且更喜欢使用 Json.NET 特定的属性,那么以下内容是等效的:

public class Language
{
    class NamedType
    {
        public string name { get; set; }
    }

    class ProficiencyType
    {
        public string level { get; set; }
        public string name { get; set; }
    }

    [JsonProperty(PropertyName = "id")]
    public int Id { get; set; }

    [JsonIgnore]
    public string Name { get; set; }

    [JsonIgnore]
    public string ProficiencyLevel { get; set; }

    [JsonIgnore]
    public string ProficiencyName { get; set; }

    [JsonProperty(PropertyName = "language", ObjectCreationHandling = ObjectCreationHandling.Replace)]
    NamedType LanguageName
    {
        get
        {
            return new NamedType { name = Name };
        }
        set
        {
            Name = (value == null ? null : value.name);
        }
    }

    [JsonProperty(PropertyName = "proficiency", ObjectCreationHandling = ObjectCreationHandling.Replace)]
    ProficiencyType Proficiency
    {
        get
        {
            return new ProficiencyType { level = ProficiencyLevel, name = ProficiencyName };
        }
        set
        {
            ProficiencyLevel = (value == null ? null : value.level);
            ProficiencyName = (value == null ? null : value.name);
        }
    }
}

关于json - 将 JSON 反序列化为扁平化类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30222921/

相关文章:

java - NullPointerException,在尝试使用 facebook graph api 从 JSON 对象检索值时?

c# - INotifyPropertyChanged 和反序列化

java - java中的序列化与反序列化

c# - 使用 JSON.NET 读取动态属性名称

c# - 使用 C# 将 JSON 字符串从 Camel 大小写转换为 Pascal 大小写

c# - 附加信息 : Error converting value [string] to type [enum]

java - 使用 Jackson 进行反序列化

json - Swift 使用 NSUserDefaults 在循环中保存 JSON 字符串

json - jq 在输出中打印字符

jquery - 如何从 JQuery getJSON 读取数据