如何将JSON对象数组反序列化为具有属性的对象?

huangapple go评论66阅读模式
英文:

How to deserialize json array of objects into object with properties?

问题

以下是翻译后的代码部分:

public class Point
{
    public string title { get; set; }
    public string category { get; set; }
    public DateTime? created { get; set; }
    public int? version { get; set; }    
}

在这里,您定义了一个名为Point的类,该类具有与JSON中的属性名称相匹配的属性。

要实现您的目标,您可以考虑使用自定义的JSON转换器来处理反序列化。在.NET 4.8 Framework中,可以使用Newtonsoft.Json库进行此操作,而不是System.Text.Json。以下是如何使用Newtonsoft.Json进行反序列化和转换的示例代码:

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using RestSharp;
using System;
using System.Collections.Generic;
using System.Linq;

public class PointConverter : JsonConverter<Point>
{
    public override Point ReadJson(JsonReader reader, Type objectType, Point existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        JObject jsonObject = JObject.Load(reader);
        Point point = new Point();

        foreach (var property in jsonObject.Properties())
        {
            string propertyName = property.Name;
            JToken propertyValue = property.Value;

            switch (propertyName)
            {
                case "title":
                    point.title = propertyValue.Value<string>();
                    break;
                case "category":
                    point.category = propertyValue.Value<string>();
                    break;
                case "created":
                    point.created = propertyValue.Value<long?>() != null ? new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(propertyValue.Value<long>().ToString()) : (DateTime?)null;
                    break;
                case "version":
                    point.version = propertyValue.Value<int?>();
                    break;
                default:
                    // Handle unknown properties if needed
                    break;
            }
        }

        return point;
    }

    public override void WriteJson(JsonWriter writer, Point value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

public class Program
{
    public static async Task Main()
    {
        RestClient client = new RestClient("your-api-url");
        RestRequest request = new RestRequest("my-views");

        // Add the custom converter to the JsonSerializer settings
        JsonSerializerSettings jsonSettings = new JsonSerializerSettings();
        jsonSettings.Converters.Add(new PointConverter());

        // Get response from API with deserialized json-data to a Point object
        var response = await client.ExecuteGetAsync<Point>(request);

        // Access the properties as needed
        string title = response.Data.title;
        string category = response.Data.category;
        DateTime? created = response.Data.created;
        int? version = response.Data.version;

        // Your desired properties are now available in the 'response' object
    }
}

这段代码演示了如何使用自定义JSON转换器PointConverter来反序列化JSON响应并将其转换为Point对象。然后,您可以按需访问Point对象的属性。请确保将Newtonsoft.Json库添加到您的项目中。

英文:

I am working with the following JSON string from api response:

{
    &quot;points&quot;: [{
            &quot;name&quot;: &quot;title&quot;,
            &quot;value&quot;: &quot;Test&quot;
        }, {
            &quot;name&quot;: &quot;category&quot;,
            &quot;value&quot;: null
        }, {
            &quot;name&quot;: &quot;created&quot;,
            &quot;value&quot;: 1550743894373
        }, {
            &quot;name&quot;: &quot;version&quot;,
            &quot;value&quot;: 1
    }]
}

the json-structure of the response is always the same, root-node "points" has 1 or more name-value pairs.

I have a class structure as follows for parsing and filling the json data

// can&#39;t use record, have to use class, i only have .NET Framework 4.8 available
public class Point
{
[JsonPropertyName(&quot;name&quot;)]
public string Name { get; set; }
[JsonPropertyName(&quot;value&quot;)]
public object Value { get; set; }
}
public class MyViews
{
[JsonPropertyName(&quot;points&quot;)]
public List&lt;Point&gt; Points { get; set; }
}

and this is my code:

using RestSharp;
// create request for API
var request = new RestRequest(&quot;my-views&quot;);
// get response from API with deserialized json-data to my Points-object
var response = await client.ExecuteGetAsync&lt;MyViews&gt;(request);
// just example of getting simple data from object
Point response_point = response.Data.Points.first(); // get first object
string title;
// check if object is a title
if (response_point.Name == &quot;title&quot;) {
title = response_point.Value; // get value of title
}}
// my goal is:
// Point response_point = response.Data;
// title = response_point.title;

My deserialization goal is to fill data in the following class structure:

public class Point
{
public string title { get; set; }
public string category { get; set; }
public DateTime? created { get; set; }
public int? version { get; set; }    
}

I want to have only one "Point" object with all name-value pairs as properties (without List in MyViews class).

Is there a way to transform the data on deserialization process, or trigger a method on Points-object after deserialization complete?

I'm using RestSharp-lib with default serializer System.Text.Json.

Thanks.

UPDATE: I'm not attached to any library, I have free choice, the only restriction I have to stick to is .NET 4.8 Framework.

答案1

得分: 1

Text.Json  Net 4.8 是有史以来最糟糕的组合。安装 Newtonsoft.Json,代码将更简单。

using Newtonsoft.Json;

var response = await client.ExecuteGetAsync(request);

var points = JObject.Parse(response.Content)["points"];

Point point = new Point();

foreach (var item in points)
{
    var val = item["value"];
    switch ((string)item["name"])
    {
        case "title": point.title = (string)val; break;
        case "category": point.category = (string)val; break;
        // case "created": point.created = (DateTime)val; break; //只有您知道日期的格式是什么
        case "version": point.version = (int?)val; break;
    }
}
英文:

Text.Json and Net 4.8 is the worst combination ever. Install Newtonsoft.Json and the code will be simpler.

using Newonsoft.Json;
var response = await client.ExecuteGetAsync(request);
var points = JObject.Parse(response.Content)[&quot;points&quot;];
Point point = new Point();
foreach (var item in points)
{
var val = item[&quot;value&quot;];
switch ((string)item[&quot;name&quot;])
{
case &quot;title&quot;: point.title = (string)val; break;
case &quot;category&quot;: point.category = (string)val; break;
// case &quot;created&quot;:point.created = (DateTime) val; break; //only you know what format is your date
case &quot;version&quot;: point.version = (int?)val; break;
}
}

答案2

得分: -1

请使用数组而不是列表:

public class Point
{
    public string title { get; set; }
    public string category { get; set; }
    public DateTime? created { get; set; }
    public int? version { get; set; }
}

public class MyViews
{
    [JsonPropertyName("points")]
    public Point[] Points { get; set; }   // <- an array of the Points
}

public class Program
{
    public static void Main()
    {
        string json = @"
        {
            ""points"": [
                {
                    ""name"": ""title"",
                    ""value"": ""Test""
                },
                {
                    ""name"": ""category"",
                    ""value"": null
                },
                {
                    ""name"": ""created"",
                    ""value"": 1550743894373
                },
                {
                    ""name"": ""version"",
                    ""value"": 1
                }
            ]
        }";
    
        MyViews myViews = new MyViews();
        // --> 在此处我们将 JSON 反序列化为 Points 数组
        myViews.Points = JsonSerializer.Deserialize<Point[]>(json);  
    
        Console.WriteLine("Deserialized Points:");
        foreach (Point point in myViews.Points)
        {
            Console.WriteLine($"Title: {point.title}");
            Console.WriteLine($"Category: {point.category}");
            Console.WriteLine($"Created: {point.created}");
            Console.WriteLine($"Version: {point.version}");
            Console.WriteLine();
        }
    
        string serializedJson = JsonSerializer.Serialize(myViews);
        Console.WriteLine("Serialized JSON:");
        Console.WriteLine(serializedJson);
    }
}
英文:

Use array instead of list:

public class Point
{
public string title { get; set; }
public string category { get; set; }
public DateTime? created { get; set; }
public int? version { get; set; }
}
public class MyViews
{
[JsonPropertyName(&quot;points&quot;)]
public Point[] Points { get; set; }   // &lt;- an array of the Points
}
public class Program
{
public static void Main()
{
string json = @&quot;{
&quot;&quot;points&quot;&quot;: [
{
&quot;&quot;name&quot;&quot;: &quot;&quot;title&quot;&quot;,
&quot;&quot;value&quot;&quot;: &quot;&quot;Test&quot;&quot;
},
{
&quot;&quot;name&quot;&quot;: &quot;&quot;category&quot;&quot;,
&quot;&quot;value&quot;&quot;: null
},
{
&quot;&quot;name&quot;&quot;: &quot;&quot;created&quot;&quot;,
&quot;&quot;value&quot;&quot;: 1550743894373
},
{
&quot;&quot;name&quot;&quot;: &quot;&quot;version&quot;&quot;,
&quot;&quot;value&quot;&quot;: 1
}
]
}&quot;;
MyViews myViews = new MyViews();
// --&gt; Here we deserialize the json to an array of Points
myViews.Points = JsonSerializer.Deserialize&lt;Point[]&gt;(json);  
Console.WriteLine(&quot;Deserialized Points:&quot;);
foreach (Point point in myViews.Points)
{
Console.WriteLine($&quot;Title: {point.title}&quot;);
Console.WriteLine($&quot;Category: {point.category}&quot;);
Console.WriteLine($&quot;Created: {point.created}&quot;);
Console.WriteLine($&quot;Version: {point.version}&quot;);
Console.WriteLine();
}
string serializedJson = JsonSerializer.Serialize(myViews);
Console.WriteLine(&quot;Serialized JSON:&quot;);
Console.WriteLine(serializedJson);
}
}

huangapple
  • 本文由 发表于 2023年6月30日 01:51:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/76583494.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定