You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Framework 4.8下如何将JSON对象数组反序列化为属性对象?

问题描述

我正在处理API返回的JSON字符串,结构如下:

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

该JSON结构固定,根节点points包含一组或多组name-value键值对。

我原本使用以下类结构解析:

// 不能用record,必须用class,因为我只能用.NET Framework 4.8
public class Point
{
    [JsonPropertyName("name")]
    public string Name { get; set; }

    [JsonPropertyName("value")]
    public object Value { get; set; }
}

public class MyViews
{
    [JsonPropertyName("points")]
    public List<Point> Points { get; set; }
}

对应的RestSharp请求代码:

using RestSharp;

// 创建API请求
var request = new RestRequest("my-views");

// 获取API响应并反序列化为MyViews对象
var response = await client.ExecuteGetAsync<MyViews>(request);

// 示例:从对象中获取数据
Point response_point = response.Data.Points.First(); // 获取第一个对象
string title;
// 判断是否是title字段
if (response_point.Name == "title") {
    title = response_point.Value.ToString(); // 获取title的值
}

// 我的目标是:
// Point response_point = response.Data;
// title = response_point.title;

我的反序列化目标是将数据填充到如下类结构中:

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

即得到一个包含所有name-value对应属性的单个Point对象,无需MyViews类中的List集合。

请问是否可以在反序列化过程中完成这个转换,或在反序列化后触发方法实现转换?我当前使用RestSharp及默认的System.Text.Json序列化器,但可自由选择序列化库,唯一限制是必须使用.NET Framework 4.8。


解决方案

方法一:使用Newtonsoft.Json自定义转换器(推荐,.NET Framework 4.8兼容性更佳)

Newtonsoft.Json(Json.NET)在.NET Framework生态中成熟稳定,自定义转换器实现灵活。

  1. 安装Newtonsoft.Json NuGet包:
Install-Package Newtonsoft.Json
  1. 实现自定义JsonConverter:
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;

public class PointConverter : JsonConverter<Point>
{
    public override Point ReadJson(JsonReader reader, Type objectType, Point existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        var jsonObject = JObject.Load(reader);
        var pointsArray = jsonObject["points"] as JArray;
        var point = new Point();

        foreach (var item in pointsArray)
        {
            var name = item["name"].ToString();
            var value = item["value"];

            switch (name)
            {
                case "title":
                    point.title = value?.ToString();
                    break;
                case "category":
                    point.category = value?.ToString();
                    break;
                case "created":
                    if (value != null && value.Type != JTokenType.Null)
                    {
                        // 将毫秒时间戳转换为DateTime
                        point.created = DateTimeOffset.FromUnixTimeMilliseconds(value.Value<long>()).DateTime;
                    }
                    break;
                case "version":
                    if (value != null && value.Type != JTokenType.Null)
                    {
                        point.version = value.Value<int>();
                    }
                    break;
            }
        }

        return point;
    }

    public override void WriteJson(JsonWriter writer, Point value, JsonSerializer serializer)
    {
        // 若无需将Point对象序列回原格式,可留空或按需实现
        throw new NotImplementedException();
    }
}
  1. 配置RestSharp使用Newtonsoft.Json并添加转换器:
using RestSharp;
using RestSharp.Serializers.NewtonsoftJson;

// 初始化RestClient时指定NewtonsoftJson序列化器
var client = new RestClient("你的API基础地址")
{
    UseNewtonsoftJson()
};

var request = new RestRequest("my-views");

// 执行请求时注入自定义转换器
var response = await client.ExecuteGetAsync<Point>(request, ct =>
{
    ct.JsonSerializerSettings.Converters.Add(new PointConverter());
});

// 直接使用转换后的对象
var myPoint = response.Data;
string title = myPoint.title;
DateTime? created = myPoint.created;

方法二:使用System.Text.Json自定义转换器

若坚持使用System.Text.Json,需先安装兼容.NET Framework 4.8的NuGet包:

Install-Package System.Text.Json
  1. 实现自定义JsonConverter:
using System;
using System.Text.Json;
using System.Text.Json.Serialization;

public class PointSystemTextJsonConverter : JsonConverter<Point>
{
    public override Point Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        using (var doc = JsonDocument.ParseValue(ref reader))
        {
            var root = doc.RootElement;
            var points = root.GetProperty("points");
            var point = new Point();

            foreach (var item in points.EnumerateArray())
            {
                var name = item.GetProperty("name").GetString();
                if (item.TryGetProperty("value", out var value))
                {
                    switch (name)
                    {
                        case "title":
                            point.title = value.GetString();
                            break;
                        case "category":
                            point.category = value.GetString();
                            break;
                        case "created":
                            if (!value.ValueKind.Equals(JsonValueKind.Null))
                            {
                                long timestamp = value.GetInt64();
                                point.created = DateTimeOffset.FromUnixTimeMilliseconds(timestamp).DateTime;
                            }
                            break;
                        case "version":
                            if (!value.ValueKind.Equals(JsonValueKind.Null))
                            {
                                point.version = value.GetInt32();
                            }
                            break;
                    }
                }
            }

            return point;
        }
    }

    public override void Write(Utf8JsonWriter writer, Point value, JsonSerializerOptions options)
    {
        throw new NotImplementedException();
    }
}
  1. 配置RestSharp使用System.Text.Json并添加转换器:
using RestSharp;
using RestSharp.Serializers.SystemTextJson;

var jsonOptions = new JsonSerializerOptions();
jsonOptions.Converters.Add(new PointSystemTextJsonConverter());

var client = new RestClient("你的API基础地址")
{
    UseSystemTextJson(jsonOptions)
};

var request = new RestRequest("my-views");
var response = await client.ExecuteGetAsync<Point>(request);

var myPoint = response.Data;
// 直接访问属性
Console.WriteLine(myPoint.title);

方法三:反序列化后手动转换(简单直接)

若不想编写自定义转换器,可先反序列化为原MyViews对象,再手动映射到目标Point类:

// 先反序列化为原MyViews结构
var response = await client.ExecuteGetAsync<MyViews>(request);
var myViews = response.Data;

// 手动映射到目标Point类
var targetPoint = new Point();
foreach (var item in myViews.Points)
{
    switch (item.Name)
    {
        case "title":
            targetPoint.title = item.Value?.ToString();
            break;
        case "category":
            targetPoint.category = item.Value?.ToString();
            break;
        case "created":
            if (item.Value is long timestamp)
            {
                targetPoint.created = DateTimeOffset.FromUnixTimeMilliseconds(timestamp).DateTime;
            }
            break;
        case "version":
            if (item.Value is int version)
            {
                targetPoint.version = version;
            }
            break;
    }
}

// 直接使用转换后的对象
string title = targetPoint.title;

内容的提问来源于stack exchange,提问作者b166er

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 13:02:16