JSON对象反序列化为List时遇问题,寻求解决方法
解决JSON反序列化为List的问题
嘿,我来帮你搞定这个反序列化的麻烦!先拆解下你的JSON结构:外层是一个数组,里面的每个元素都包含returnValue字段,而returnValue又是一个存着业务数据的数组,还有MongoDB风格的$date时间格式——这俩点大概率是你卡壳的核心原因,下面分两种常用语言给你具体解决方案:
一、C# 环境(用Newtonsoft.Json)
1. 定义对应实体类
首先得把JSON里的字段映射到实体类上,注意字段名的对应,还有处理$date的特殊格式:
// 业务数据实体 public class FacilityRecord { [JsonProperty("facility")] public string Facility { get; set; } [JsonProperty("recrd_desc")] public string RecordDescription { get; set; } [JsonProperty("update_time")] public DateTime UpdateTime { get; set; } [JsonProperty("control_num")] public int ControlNumber { get; set; } [JsonProperty("starttime")] public DateTime StartTime { get; set; } [JsonProperty("endtime")] public DateTime EndTime { get; set; } [JsonProperty("can_exchange_rate")] public int CanExchangeRate { get; set; } } // 外层包装类,对应JSON里的顶层数组元素 public class ApiResponse { [JsonProperty("returnValue")] public List<FacilityRecord> ReturnValue { get; set; } }
2. 自定义日期转换器处理$date
默认的序列化器不认识{"$date": 时间戳}这种格式,所以我们写个转换器把毫秒级时间戳转成DateTime:
public class UnixDateTimeConverter : JsonConverter<DateTime> { public override DateTime ReadJson(JsonReader reader, Type objectType, DateTime existingValue, bool hasExistingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.StartObject) { var dateObj = JObject.Load(reader); if (dateObj.TryGetValue("$date", out var timestampToken) && timestampToken.Type == JTokenType.Integer) { return DateTimeOffset.FromUnixTimeMilliseconds((long)timestampToken).DateTime; } } throw new JsonSerializationException("无法解析MongoDB格式的日期"); } public override void WriteJson(JsonWriter writer, DateTime value, JsonSerializer serializer) { writer.WriteStartObject(); writer.WritePropertyName("$date"); writer.WriteValue(new DateTimeOffset(value).ToUnixTimeMilliseconds()); writer.WriteEndObject(); } }
3. 执行反序列化
配置好转换器后,就可以把JSON转成List了:
// 替换成你的完整JSON字符串 string jsonContent = "[{ \"returnValue\": [{ \"facility\": \"DRIO\", ... }] }]"; var serializerSettings = new JsonSerializerSettings { Converters = { new UnixDateTimeConverter() } }; // 先反序列化顶层数组 var apiResponses = JsonConvert.DeserializeObject<List<ApiResponse>>(jsonContent, serializerSettings); // 提取returnValue里的业务数据列表 List<FacilityRecord> targetList = apiResponses.SelectMany(resp => resp.ReturnValue).ToList();
二、Java 环境(用Jackson)
1. 定义实体类
同样先映射字段,并用@JsonDeserialize指定自定义日期转换器:
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import java.util.Date; public class FacilityRecord { @JsonProperty("facility") private String facility; @JsonProperty("recrd_desc") private String recordDesc; @JsonProperty("update_time") @JsonDeserialize(using = MongoDateDeserializer.class) private Date updateTime; @JsonProperty("control_num") private int controlNum; @JsonProperty("starttime") @JsonDeserialize(using = MongoDateDeserializer.class) private Date startTime; @JsonProperty("endtime") @JsonDeserialize(using = MongoDateDeserializer.class) private Date endTime; @JsonProperty("can_exchange_rate") private int canExchangeRate; // 记得生成所有字段的getter和setter方法 } // 顶层包装类 import com.fasterxml.jackson.annotation.JsonProperty; import java.util.List; public class ApiResponse { @JsonProperty("returnValue") private List<FacilityRecord> returnValue; public List<FacilityRecord> getReturnValue() { return returnValue; } public void setReturnValue(List<FacilityRecord> returnValue) { this.returnValue = returnValue; } }
2. 实现日期反序列化器
import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonNode; import java.io.IOException; import java.util.Date; public class MongoDateDeserializer extends JsonDeserializer<Date> { @Override public Date deserialize(JsonParser parser, DeserializationContext context) throws IOException { JsonNode dateNode = parser.getCodec().readTree(parser); long timestamp = dateNode.get("$date").asLong(); return new Date(timestamp); } }
3. 完成反序列化
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import java.util.List; import java.util.stream.Collectors; public class DeserializeDemo { public static void main(String[] args) throws IOException { String jsonContent = "[{ \"returnValue\": [{ \"facility\": \"DRIO\", ... }] }]"; ObjectMapper mapper = new ObjectMapper(); // 反序列化顶层数组 List<ApiResponse> apiResponses = mapper.readValue(jsonContent, new TypeReference<List<ApiResponse>>() {}); // 提取业务数据列表 List<FacilityRecord> targetList = apiResponses.stream() .flatMap(resp -> resp.getReturnValue().stream()) .collect(Collectors.toList()); } }
额外提醒
- 你的JSON末尾看起来是截断的(
endtime": { "$date": 15445762... }]),一定要确保JSON是完整且格式正确的,不然反序列化会直接抛出格式错误异常。 - 如果用其他序列化库(比如C#的System.Text.Json),核心思路还是:定义对应实体类 + 自定义转换器处理MongoDB日期格式。
内容的提问来源于stack exchange,提问作者SoftwareDveloper
相关产品推荐
相关产品推荐

