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

.NET中如何反序列化含无字段值的JSON数组?

如何反序列化混合类型的JSON数组到.NET对象

问题场景

我正在开发一个从特定Web服务获取JSON消息的应用,返回的JSON是混合类型数组:

[  
  15,  
  "5667",  
  {    
    "status":"Uploaded",    
    "uploadTime":"2023-07-05T11:03:19+00:00",    
    "progress":12  
  }
]

我尝试用以下.NET类直接反序列化:

public class WebServiceNotification{  
  public int typeId { get; set; }  
  public string msgId { get; set; }  
  public string status { get; set; }  
  public string uploadTime{ get; set; }  
  public int progress{ get; set; }
}

使用Newtonsoft.Json和System.Text.Json均失败,测试代码如下(已修正字符串引号转义问题):

string msgFromWebService = "[15,\"5667\",{\"status\":\"Uploaded\",\"uploadTime\":\"2023-07-05T11:03:19+00:00\",\"progress\":12}]";

var ocppMsg1 = JsonSerializer.Deserialize<WebServiceNotification>(msgFromWebService);
var ocppMsg2 = JsonConvert.DeserializeObject<WebServiceNotification>(msgFromWebService);

报错信息

  • System.Text.Json报错:

Unhandled exception. System.Text.Json.JsonException: '1' is an invalid start of a property name. Expected a '"'. Path: $ | LineNumber: 0 | BytePositionInLine: 1.

  • Newtonsoft.Json报错:

Unhandled exception. Newtonsoft.Json.JsonReaderException: Invalid JavaScript property identifier character: ,. Path '', line 1, position 3.

核心问题:能否反序列化这种包含无对应字段纯值(如15和"5667")的JSON消息?


解决方案

可以实现反序列化。问题根源是你试图将JSON数组直接映射到**.NET对象**,两者结构不匹配。需要通过拆分数组元素或自定义转换器来完成映射。

方法1:手动拆分数组元素映射(快速实现)

先将JSON反序列化为数组,再将数组元素逐个赋值到目标类。

使用System.Text.Json

var jsonArray = JsonSerializer.Deserialize<object[]>(msgFromWebService);
if (jsonArray != null && jsonArray.Length >=3)
{
    var notification = new WebServiceNotification
    {
        typeId = Convert.ToInt32(jsonArray[0]),
        msgId = jsonArray[1] as string,
        status = ((JsonElement)jsonArray[2]).GetProperty("status").GetString(),
        uploadTime = ((JsonElement)jsonArray[2]).GetProperty("uploadTime").GetString(),
        progress = ((JsonElement)jsonArray[2]).GetProperty("progress").GetInt32()
    };
}

使用Newtonsoft.Json

var jsonArray = JsonConvert.DeserializeObject<JArray>(msgFromWebService);
if (jsonArray != null && jsonArray.Count >=3)
{
    var notification = new WebServiceNotification
    {
        typeId = jsonArray[0].Value<int>(),
        msgId = jsonArray[1].Value<string>(),
        status = jsonArray[2]["status"].Value<string>(),
        uploadTime = jsonArray[2]["uploadTime"].Value<string>(),
        progress = jsonArray[2]["progress"].Value<int>()
    };
}

方法2:自定义JsonConverter(优雅复用)

如果需要频繁处理这类JSON,可自定义转换器,让序列化库直接将数组映射到目标类。

针对System.Text.Json的转换器

public class WebServiceNotificationConverter : JsonConverter<WebServiceNotification>
{
    public override WebServiceNotification Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        if (reader.TokenType != JsonTokenType.StartArray)
            throw new JsonException("JSON格式应为数组");
        
        reader.Read(); // 跳过数组起始标记
        var notification = new WebServiceNotification();
        
        // 读取第一个元素:typeId
        if (reader.TokenType == JsonTokenType.Number)
        {
            notification.typeId = reader.GetInt32();
            reader.Read();
        }
        
        // 读取第二个元素:msgId
        if (reader.TokenType == JsonTokenType.String)
        {
            notification.msgId = reader.GetString();
            reader.Read();
        }
        
        // 读取第三个元素:嵌套对象
        if (reader.TokenType == JsonTokenType.StartObject)
        {
            var obj = JsonSerializer.Deserialize<JsonElement>(ref reader, options);
            notification.status = obj.GetProperty("status").GetString();
            notification.uploadTime = obj.GetProperty("uploadTime").GetString();
            notification.progress = obj.GetProperty("progress").GetInt32();
            reader.Read(); // 跳过对象结束标记
        }
        
        reader.Read(); // 跳过数组结束标记
        return notification;
    }

    public override void Write(Utf8JsonWriter writer, WebServiceNotification value, JsonSerializerOptions options)
    {
        // 如需序列化回JSON数组,实现对应逻辑
        writer.WriteStartArray();
        writer.WriteNumberValue(value.typeId);
        writer.WriteStringValue(value.msgId);
        writer.WriteStartObject();
        writer.WriteString("status", value.status);
        writer.WriteString("uploadTime", value.uploadTime);
        writer.WriteNumber("progress", value.progress);
        writer.WriteEndObject();
        writer.WriteEndArray();
    }
}

使用方式:

var options = new JsonSerializerOptions();
options.Converters.Add(new WebServiceNotificationConverter());
var ocppMsg = JsonSerializer.Deserialize<WebServiceNotification>(msgFromWebService, options);

针对Newtonsoft.Json的转换器

public class WebServiceNotificationConverter : JsonConverter<WebServiceNotification>
{
    public override WebServiceNotification ReadJson(JsonReader reader, Type objectType, WebServiceNotification existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        if (reader.TokenType != JsonToken.StartArray)
            throw new JsonReaderException("JSON格式应为数组");
        
        var notification = new WebServiceNotification();
        reader.Read(); // 跳过数组起始标记
        
        // 读取typeId
        if (reader.TokenType == JsonToken.Integer)
        {
            notification.typeId = (int)reader.Value;
            reader.Read();
        }
        
        // 读取msgId
        if (reader.TokenType == JsonToken.String)
        {
            notification.msgId = (string)reader.Value;
            reader.Read();
        }
        
        // 读取嵌套对象
        if (reader.TokenType == JsonToken.StartObject)
        {
            var obj = JObject.Load(reader);
            notification.status = obj["status"].Value<string>();
            notification.uploadTime = obj["uploadTime"].Value<string>();
            notification.progress = obj["progress"].Value<int>();
            reader.Read(); // 跳过对象结束标记
        }
        
        reader.Read(); // 跳过数组结束标记
        return notification;
    }

    public override void WriteJson(JsonWriter writer, WebServiceNotification value, JsonSerializer serializer)
    {
        // 如需序列化回JSON数组,实现对应逻辑
        writer.WriteStartArray();
        writer.WriteValue(value.typeId);
        writer.WriteValue(value.msgId);
        writer.WriteStartObject();
        writer.WritePropertyName("status");
        writer.WriteValue(value.status);
        writer.WritePropertyName("uploadTime");
        writer.WriteValue(value.uploadTime);
        writer.WritePropertyName("progress");
        writer.WriteValue(value.progress);
        writer.WriteEndObject();
        writer.WriteEndArray();
    }
}

使用方式:

var ocppMsg = JsonConvert.DeserializeObject<WebServiceNotification>(msgFromWebService, new WebServiceNotificationConverter());

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 13:13:15