【问题标题】:C# - Json deserialize object with child attributesC# - Json 反序列化具有子属性的对象
【发布时间】:2018-05-16 21:58:54
【问题描述】:

我有以下 json:

{
   "issue" : 
   {
      "id": 1,
      "project":
      {
         "id":1,
         "name":"name of project"
      }
   }
}

我正在尝试将此 json 反序列化为以下类:

public class Issue
{
    public int? id { get; set; }
    public int project_id { get; set; }
    public string project_name { get; set; }
}

有没有办法获取子属性并设置为父亲?

【问题讨论】:

  • 首先反序列化 json 它是根据类。然后将其映射到您的对象。
  • 类似这样的东西:stackoverflow.com/a/32783339/6560478。周围有很多骗子,而且有很多方法可以做到这一点。
  • 反序列化不起作用,反序列化中从未设置project_id值。
  • "its based on class" 我的意思是使用 Json2Csharp 或 Visualstudio 特殊粘贴来找到正确的类。你有一个 json 有点像一个对象的文本表示。如果您想要其他对象,您必须: 1 从其表示加载对象(反序列化),然后映射到新对象。

标签: c# json serialization attributes


【解决方案1】:

最简单的解决方案之一是转换为JObject 并使用它从中创建所需的对象。

var jObject = JsonConvert.DeserializeObject<JObject>(text);

var issue = new Issue() {id = (int?)jObject["issue"]["id"], project_id = (int)jObject["issue"]["project"]["id"], project_name = (string)jObject["issue"]["project"]["name"]};

下面的代码就是提到的:

using System;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

public class Issue
{
    public int? id { get; set; }
    public int project_id { get; set; }
    public string project_name { get; set; }

    public override string ToString()
    {
        return "Id: " + id + " project Id: " + project_id + " project name : " + project_name;
    }
}


public class Program
{
    public static void Main()
    {
        var text = "{ \"issue\" :  { \"id\": 1, \"project\": { \"id\": 2, \"name\":\"name of project\" }}}";

        var jObject = JsonConvert.DeserializeObject<JObject>(text);

        var issue = new Issue() {id = (int?)jObject["issue"]["id"], project_id = (int)jObject["issue"]["project"]["id"], project_name = (string)jObject["issue"]["project"]["name"]};
        Console.WriteLine(issue);
    }
}

您可以在此处查看Live demo

【讨论】:

  • 这可能是一个解决方案,但这是一个干净的代码和一个好的做法?
  • 分析这段代码,这给了我一个解决方案,只需把它放在一个映射器类中,让更干净!谢谢你的光。
【解决方案2】:

您需要为project 创建新类:

问题类别:

public class Issue
{
    public int id { get; set; }
    public Project project { get; set; }
}

项目类:

public class Project
{
    public int id { get; set; }
    public String name { get; set; }
}

如果你真的需要在你的问题类中有project_idproject_name,你可以这样做:

public class Issue
{
    public int id { get; set; }
    public Project project { get; set; }

    public int getProjectId() {
        return this.getProject.getId;
    }
    //Do the same for projectName
}

希望对您有所帮助。

【讨论】:

  • OP 希望项目属性成为基础对象的一部分,而不是创建新对象。
  • 你的 JSONObject Issue 属性有一个 project JSONObject。所以,你的project.idproject.nameproject 的属性
  • 是的,我正在寻找类似的东西:JsonProperty("project/id")。但这不起作用。
  • @JsonProperty("yourValueName") 设置你的名字在你的吸气剂之前使用。例如:@JsonProperty("nameToUse") public String getAnotherName() {} //返回“nameToUse”属性见:github.com/FasterXML/jackson-annotations/wiki/…
【解决方案3】:

Here 是一种方法

这是代码

public class ConventionBasedConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return typeof(YOUR-OBJECT).IsAssignableFrom(objectType);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var daat = JObject.Load(reader);
        var yourObject = new YOUR-OBJECT();

        foreach (var prop in yourObject GetType().GetProperties(BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance))
        {
            var attr = prop.GetCustomAttributes(false).FirstOrDefault();
            if (attr != null)
            {
                var propName = ((JsonPropertyAttribute)attr).PropertyName;
                if (!string.IsNullOrWhiteSpace(propName))
                {
                    //split by the delimiter, and traverse recursevly according to the path
                    var conventions = propName.Split('/');
                    object propValue = null;
                    JToken token = null;
                    for (var i = 0; i < conventions.Length; i++)
                    {
                        if (token == null)
                        {
                            token = daat[conventions[i]];
                        }
                        else {
                            token = token[conventions[i]];
                        }
                        if (token == null)
                        {
                            //silent fail: exit the loop if the specified path was not found
                            break;
                        }
                        else
                        {
                            //store the current value
                            if (token is JValue)
                            {
                                propValue = ((JValue)token).Value;
                            }
                        }
                    }

                    if (propValue != null)
                    {
                        //workaround for numeric values being automatically created as Int64 (long) objects.
                        if (propValue is long && prop.PropertyType == typeof(Int32))
                        {
                            prop.SetValue(yourObject, Convert.ToInt32(propValue));
                        }
                        else
                        {
                            prop.SetValue(yourObject, propValue);
                        }
                    }
                }
            }
        }
        return yourObject;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
    }
}

然后像这样使用它:

 var settings = new JsonSerializerSettings();
 settings.Converters.Add(new ConventionBasedConverter());
 JsonConvert.DeserializeObject<YOUR-OBJECT>(jsonString, settings);

【讨论】:

    【解决方案4】:

    这是另一种方法。使用Cinchoo ETL - 一个带有 JSON 路径的开源库,您可以用几行代码进行反序列化

    public class Issue
    {
        [ChoJSONRecordField(JSONPath = "$..id")]
        public int? id { get; set; }
        [ChoJSONRecordField(JSONPath = "$..project.id")]
        public int project_id { get; set; }
        [ChoJSONRecordField(JSONPath = "$..project.name")]
        public string project_name { get; set; }
    }
    
    static void Sample33()
    {
        string json = @"{
           ""issue"" : 
           {
              ""id"": 1,
              ""project"":
              {
                 ""id"":1,
                 ""name"":""name of project""
              }
           }
        }";
        var issue = ChoJSONReader<Issue>.LoadText(json).First();
    }
    

    免责声明:我是这个库的作者。

    【讨论】:

      猜你喜欢
      • 2017-08-27
      • 2021-02-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-09
      • 2019-10-06
      相关资源
      最近更新 更多