如何在C#或Java中将特定JSON结构解析为对象数组?
问题还原
原JSON结构(示例):
{ "ASDAS": { "g": 123, "f": { "field1": "value1", "field2": 456 } }, "XYZ": { "g": 789, "f": { "field1": "value2", "field2": 0 } } }
期望转换后的对象数组结构:
[ { "name": "ASDAS", "g": 123, "f": { "field1": "value1", "field2": 456 } }, { "name": "XYZ", "g": 789, "f": { "field1": "value2", "field2": 0 } } ]
C# 实现方案
针对大文件场景,推荐使用流式解析减少内存开销,以下提供两种主流序列化库的实现:
1. 使用System.Text.Json(.NET Core/.NET 5+ 内置)
首先定义对应实体类:
// 对应原JSON中的f结构体 public class FStruct { // 根据实际字段调整,字段名需与JSON一致,或用[JsonPropertyName]指定映射 public string Field1 { get; set; } public int Field2 { get; set; } } // 目标数组的元素类 public class TargetItem { public string Name { get; set; } public int G { get; set; } public FStruct F { get; set; } }
流式解析代码:
using System.Text.Json; using System.Collections.Generic; using System.IO; public List<TargetItem> ParseLargeJson(string filePath) { var targetList = new List<TargetItem>(); // 流式读取文件,避免一次性加载整个JSON到内存 using var stream = File.OpenRead(filePath); using var doc = JsonDocument.Parse(stream, new JsonDocumentOptions { AllowTrailingCommas = true }); // 遍历顶级键值对 foreach (var property in doc.RootElement.EnumerateObject()) { var item = new TargetItem { Name = property.Name, G = property.Value.GetProperty("g").GetInt32(), F = property.Value.GetProperty("f").Deserialize<FStruct>() }; targetList.Add(item); } return targetList; }
2. 使用Newtonsoft.Json(Json.NET)
实体类与上述一致,解析代码:
using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System.Collections.Generic; using System.IO; public List<TargetItem> ParseLargeJsonWithNewtonsoft(string filePath) { var targetList = new List<TargetItem>(); using var reader = new JsonTextReader(new StreamReader(filePath)); var jsonDict = JsonSerializer.Deserialize<Dictionary<string, JObject>>(reader); foreach (var kvp in jsonDict) { var item = new TargetItem { Name = kvp.Key, G = kvp.Value["g"].Value<int>(), F = kvp.Value["f"].ToObject<FStruct>() }; targetList.Add(item); } return targetList; }
Java 实现方案
同样针对大文件场景,推荐Jackson的流式API,以下是两种库的实现:
1. 使用Jackson(主流高性能序列化库)
定义实体类:
import com.fasterxml.jackson.annotation.JsonProperty; // 对应原JSON中的f结构体 public class FStruct { @JsonProperty("field1") private String field1; @JsonProperty("field2") private int field2; // Getter和Setter方法 public String getField1() { return field1; } public void setField1(String field1) { this.field1 = field1; } public int getField2() { return field2; } public void setField2(int field2) { this.field2 = field2; } } // 目标数组的元素类 public class TargetItem { private String name; private int g; private FStruct f; // Getter和Setter方法 public String getName() { return name; } public void setName(String name) { this.name = name; } public int getG() { return g; } public void setG(int g) { this.g = g; } public FStruct getF() { return f; } public void setF(FStruct f) { this.f = f; } }
流式解析代码:
import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.File; import java.util.ArrayList; import java.util.List; public class JsonParserUtil { public static List<TargetItem> parseLargeJson(String filePath) throws Exception { List<TargetItem> targetList = new ArrayList<>(); ObjectMapper mapper = new ObjectMapper(); JsonFactory factory = mapper.getFactory(); // 流式解析,逐token处理 try (JsonParser parser = factory.createParser(new File(filePath))) { // 跳过JSON开头的{ parser.nextToken(); while (parser.nextToken() != JsonToken.END_OBJECT) { String key = parser.getCurrentName(); // 进入当前键对应的值对象 parser.nextToken(); TargetItem item = new TargetItem(); item.setName(key); // 遍历值对象内的字段 while (parser.nextToken() != JsonToken.END_OBJECT) { String fieldName = parser.getCurrentName(); parser.nextToken(); if ("g".equals(fieldName)) { item.setG(parser.getIntValue()); } else if ("f".equals(fieldName)) { // 反序列化f结构体 FStruct f = mapper.readValue(parser, FStruct.class); item.setF(f); } } targetList.add(item); } } return targetList; } }
2. 使用Gson
实体类与上述一致,解析代码:
import com.google.gson.Gson; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import java.io.FileReader; import java.util.ArrayList; import java.util.List; import java.util.Map; public class GsonParserUtil { public static List<TargetItem> parseLargeJson(String filePath) throws Exception { List<TargetItem> targetList = new ArrayList<>(); Gson gson = new Gson(); try (FileReader reader = new FileReader(filePath)) { JsonObject jsonObj = JsonParser.parseReader(reader).getAsJsonObject(); // 遍历顶级键值对 for (Map.Entry<String, JsonElement> entry : jsonObj.entrySet()) { JsonObject valueObj = entry.getValue().getAsJsonObject(); TargetItem item = new TargetItem(); item.setName(entry.getKey()); item.setG(valueObj.get("g").getAsInt()); item.setF(gson.fromJson(valueObj.get("f"), FStruct.class)); targetList.add(item); } } return targetList; } }
通用解析思路
- 核心逻辑:遍历JSON的顶级键值对,将每个键映射为目标对象的
name字段,提取值对象中的g字段,将f字段反序列化为对应结构体,最后收集所有对象到数组/列表。 - 大文件优化:优先使用流式解析API,避免一次性加载整个JSON到内存,降低内存占用,提升处理效率。
- 字段适配:根据实际JSON中
f的字段调整实体类属性,若字段名不匹配,可通过序列化特性(如C#的[JsonPropertyName]、Java的@JsonProperty)指定映射关系。
内容的提问来源于stack exchange,提问作者Cn4
相关产品推荐
相关产品推荐

