代码中如何解析此类JSON请求?结构化改写后输出不一致问题
问题分析与解决方案
差异原因
你的代码输出和初始请求不一致,核心是两个问题:
- 数据结构不匹配:初始请求的
locations是字符串数组(每个元素是逗号分隔的经纬度字符串),而你定义的Request类中Locations是对象数组(每个元素包含Latitude和Longitude两个数值字段),序列化后自然生成对象结构的JSON,而非字符串数组。 - 命名规则不一致:初始JSON的键是小写的
locations,但你的C#属性是大写的Locations,默认序列化会直接使用C#属性名作为JSON键名,导致键名大小写不匹配。
一、如何解析初始JSON请求
要把初始的字符串数组格式JSON解析为你的Request类对象,需要手动分割每个经纬度字符串,转换为Locations对象:
示例代码(使用Newtonsoft.Json)
// 初始JSON字符串 string originalJson = @"{""locations"" : [""53.44059300,-2.22992800"",""53.36246000,-2.26683200""]}"; // 解析JSON var jObject = Newtonsoft.Json.Linq.JObject.Parse(originalJson); var request = new Request(); foreach (string locString in jObject["locations"].Values<string>()) { // 分割经纬度字符串 string[] coords = locString.Split(','); if (coords.Length == 2 && double.TryParse(coords[0], out double latitude) && double.TryParse(coords[1], out double longitude)) { request.Locations.Add(new Locations { Latitude = latitude, Longitude = longitude }); } }
二、如何生成与初始请求一致的输出
要将Request类对象序列化为字符串数组格式的JSON,需要自定义JSON序列化逻辑,覆盖默认的对象序列化行为:
方法1:自定义JsonConverter(推荐)
创建一个针对Request类的转换器,控制序列化和反序列化的逻辑:
using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; public class RequestConverter : JsonConverter<Request> { // 序列化:将Request对象转为字符串数组格式的JSON public override void WriteJson(JsonWriter writer, Request value, JsonSerializer serializer) { writer.WriteStartObject(); writer.WritePropertyName("locations"); // 匹配初始JSON的小写键名 writer.WriteStartArray(); foreach (var location in value.Locations) { // 将Latitude和Longitude拼接为逗号分隔的字符串 writer.WriteValue($"{location.Latitude},{location.Longitude}"); } writer.WriteEndArray(); writer.WriteEndObject(); } // 反序列化:将字符串数组格式的JSON转为Request对象 public override Request ReadJson(JsonReader reader, Type objectType, Request existingValue, bool hasExistingValue, JsonSerializer serializer) { var jObject = JObject.Load(reader); var request = existingValue ?? new Request(); foreach (string locString in jObject["locations"].Values<string>()) { string[] coords = locString.Split(','); if (coords.Length == 2 && double.TryParse(coords[0], out double latitude) && double.TryParse(coords[1], out double longitude)) { request.Locations.Add(new Locations { Latitude = latitude, Longitude = longitude }); } } return request; } }
使用转换器序列化
var request = new Request(); // 假设已填充request.Locations的数据 var settings = new JsonSerializerSettings(); settings.Converters.Add(new RequestConverter()); // 生成与初始请求格式一致的JSON string outputJson = JsonConvert.SerializeObject(request, settings);
方法2:临时修改类结构(简单场景)
如果只是临时生成对应格式,可以直接构造JSON字符串:
var locationsStrings = request.Locations.Select(loc => $"{loc.Latitude},{loc.Longitude}"); string outputJson = $"{{\"locations\": [{string.Join(",", locationsStrings.Select(s => $"\"{s}\""))}]}}";
补充:键名大小写匹配
如果不需要自定义转换器,仅需修正键名大小写,可以在Request类的属性上添加JsonProperty特性:
internal class Request : DerivedA { [JsonProperty("locations")] // 指定JSON键名为小写 public List<Locations> Locations { get; set; } = new List<Locations>(); }
内容的提问来源于stack exchange,提问作者lakykytik
相关产品推荐
相关产品推荐

