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

如何在JSON反序列化与复杂工厂模式下避免重复数组

问题:移除Room类中的ItemStrings字段的最优实现方式

我正在开发一个文本冒险游戏及引擎项目,希望尽可能多的游戏内容用JSON编写,通过工厂链在启动时实例化游戏世界。当前代码中Room类同时包含Items和ItemStrings字段,希望移除ItemStrings,且保持调用方式Factory.MakeRoom("treasureRoom");不变。

现有代码示例:

现有Room类

public class Room{
    public List<Item> Items;
    public List<string> ItemStrings;
    public string Description;

    public void AddRoom(Room room){
        Items.Add(room);
    }
}

现有Item类

public class Item{
    string Name;
    string Description;
}

现有JSON配置示例

treasureRoom.json

{
  "ItemStrings": [
    "pie",
    "shoe"
  ],
  "Description": "A Fancy Room"
}

pie.json

{
  "Name" : "pie",
  "Description": "its a pie"
}

shoe.json

{
  "Name" : "shoe",
  "Description": "its a shoe"
}

现有工厂类

public static Room MakeRoom(string roomName)
{
    var room = JsonConvert.DeserializeObject<Room>(Util.Readfile($"{basePath}/GameObjects/Rooms/{roomName}.json"));
    foreach(var item in room.ItemStrings)
    {
        room.AddItem(Factory.MakeItem(item));
    }
    return room;
}

public static Item MakeItem(string fileName){
    return JsonConvert.DeserializeObject<Item>(Util.Readfile($"{basePath}/GameObjects/Items/{itemName}.json"));
}

最优实现方案

以下两种方案均无需修改现有JSON文件、保持Factory.MakeRoom调用方式不变,可彻底移除Room类的ItemStrings字段:

方案一:自定义JSON转换器(推荐)

通过自定义JsonConverter,在反序列化Room时直接处理JSON中的ItemStrings字段,自动加载并实例化对应Item,将逻辑封装在转换器中,让Room类更简洁。

步骤1:修改Room类,移除ItemStrings并修正方法

public class Room{
    public List<Item> Items = new List<Item>(); // 初始化避免空引用异常
    public string Description;

    // 修正原代码笔误:原AddRoom方法逻辑错误,应为AddItem
    public void AddItem(Item item){
        Items.Add(item);
    }
}

步骤2:实现Room自定义转换器

public class RoomConverter : JsonConverter<Room>
{
    public override Room ReadJson(JsonReader reader, Type objectType, Room existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        var jsonObj = JObject.Load(reader);
        var room = new Room();
        
        // 反序列化基础描述字段
        room.Description = jsonObj["Description"]?.ToString();
        
        // 解析ItemStrings并加载对应Item实例
        var itemNames = jsonObj["ItemStrings"]?.ToObject<List<string>>();
        if(itemNames != null)
        {
            foreach(var itemName in itemNames)
            {
                var item = Factory.MakeItem(itemName);
                room.AddItem(item);
            }
        }
        
        return room;
    }

    public override void WriteJson(JsonWriter writer, Room value, JsonSerializer serializer)
    {
        // 如需序列化Room,可反向将Items转为ItemStrings写入JSON
        var jsonObj = new JObject();
        jsonObj["Description"] = value.Description;
        jsonObj["ItemStrings"] = new JArray(value.Items.Select(i => i.Name));
        jsonObj.WriteTo(writer);
    }
}

步骤3:修改MakeRoom方法使用转换器

public static Room MakeRoom(string roomName)
{
    var jsonSettings = new JsonSerializerSettings();
    jsonSettings.Converters.Add(new RoomConverter());
    
    var jsonContent = Util.Readfile($"{basePath}/GameObjects/Rooms/{roomName}.json");
    return JsonConvert.DeserializeObject<Room>(jsonContent, jsonSettings);
}

方案二:DTO数据传输对象中转

定义一个与现有Room JSON结构完全匹配的DTO类,先反序列化到DTO,再映射为Room实例,隔离JSON结构与业务实体。

步骤1:定义RoomDTO类

public class RoomDTO{
    public List<string> ItemStrings;
    public string Description;
}

步骤2:修改Room类,移除ItemStrings

public class Room{
    public List<Item> Items = new List<Item>();
    public string Description;

    public void AddItem(Item item){
        Items.Add(item);
    }
}

步骤3:修改MakeRoom方法,用DTO中转

public static Room MakeRoom(string roomName)
{
    var jsonContent = Util.Readfile($"{basePath}/GameObjects/Rooms/{roomName}.json");
    var roomDTO = JsonConvert.DeserializeObject<RoomDTO>(jsonContent);
    
    var room = new Room();
    room.Description = roomDTO.Description;
    
    foreach(var itemName in roomDTO.ItemStrings)
    {
        room.AddItem(Factory.MakeItem(itemName));
    }
    
    return room;
}

方案对比
  • 方案一:逻辑封装性强,工厂方法更简洁,适合需要长期维护、后续可能扩展更多自定义反序列化逻辑的场景。
  • 方案二:实现简单、代码量少,适合快速迭代、业务逻辑较简单的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 19:27:37