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

使用C#读取MongoDB时如何转换GoodsList的name+value格式?

解决方案

方案一:手动转换(快速实现)

先将MongoDB数据读取为BsonDocument,再手动提取字段并转换GoodsList的格式,这种方式逻辑直观,适合快速解决需求。

步骤与代码示例

  1. 定义目标实体类:
public class Order
{
    // 用BsonElement指定MongoDB中的字段名,解决大小写差异问题
    [BsonElement("StatusText")]
    public string StatusText { get; set; }
    
    [BsonElement("goodsList")]
    public List<GoodsItem> GoodsList { get; set; }
    
    [BsonElement("Notes")]
    public string Notes { get; set; }
}

public class GoodsItem
{
    public string Name { get; set; }
    public decimal Price { get; set; }
    // 添加其他需要映射的字段
}
  1. 读取并转换数据:
// 假设已获取MongoDB集合实例
var collection = mongoDatabase.GetCollection<BsonDocument>("your-collection-name");
var filter = Builders<BsonDocument>.Filter.Empty;
var rawDocument = collection.Find(filter).FirstOrDefault();

if (rawDocument == null) return null;

var order = new Order
{
    StatusText = rawDocument.GetValue("StatusText", BsonString.Empty).AsString,
    Notes = rawDocument.GetValue("Notes", BsonString.Empty).AsString,
    GoodsList = new List<GoodsItem>()
};

// 处理嵌套的goodsList数组
if (rawDocument.Contains("goodsList") && rawDocument["goodsList"] is BsonArray outerArray)
{
    foreach (var innerArray in outerArray.OfType<BsonArray>())
    {
        var goodsItem = new GoodsItem();
        foreach (var kvDoc in innerArray.OfType<BsonDocument>())
        {
            var fieldName = kvDoc.GetValue("name").AsString.ToLower();
            var fieldValue = kvDoc.GetValue("value");

            // 根据字段名映射到GoodsItem属性
            switch (fieldName)
            {
                case "name":
                    goodsItem.Name = fieldValue.AsString;
                    break;
                case "price":
                    goodsItem.Price = fieldValue.AsDecimal;
                    break;
                // 新增其他字段的映射逻辑
            }
        }
        order.GoodsList.Add(goodsItem);
    }
}

方案二:自定义MongoDB序列化器(复用性高)

通过实现MongoDB的IBsonSerializer接口,自定义GoodsItem的反序列化逻辑,后续读取数据时可直接用实体类映射,无需重复编写转换代码。

步骤与代码示例

  1. 实现自定义序列化器:
public class GoodsItemSerializer : IBsonSerializer<GoodsItem>
{
    public Type ValueType => typeof(GoodsItem);

    public GoodsItem Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
    {
        // 读取内层数组(每个内层数组对应一个GoodsItem)
        var innerArray = context.Reader.ReadBsonArray();
        var goodsItem = new GoodsItem();

        foreach (var bsonDoc in innerArray.OfType<BsonDocument>())
        {
            var fieldName = bsonDoc["name"].AsString.ToLower();
            var fieldValue = bsonDoc["value"];

            switch (fieldName)
            {
                case "name":
                    goodsItem.Name = fieldValue.AsString;
                    break;
                case "price":
                    goodsItem.Price = fieldValue.AsDecimal;
                    break;
                // 其他字段映射
            }
        }

        return goodsItem;
    }

    // 如果不需要将数据写回MongoDB,可直接抛出异常
    public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, GoodsItem value)
    {
        throw new NotImplementedException("序列化逻辑未实现");
    }

    // 显式实现非泛型接口方法
    object IBsonSerializer.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
    {
        return Deserialize(context, args);
    }

    void IBsonSerializer.Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value)
    {
        Serialize(context, args, (GoodsItem)value);
    }
}
  1. 绑定序列化器到实体类:
public class Order
{
    [BsonElement("StatusText")]
    public string StatusText { get; set; }
    
    [BsonElement("goodsList")]
    // 指定自定义序列化器处理GoodsList的反序列化
    [BsonSerializer(typeof(GoodsItemSerializer))]
    public List<GoodsItem> GoodsList { get; set; }
    
    [BsonElement("Notes")]
    public string Notes { get; set; }
}
  1. 直接读取为实体类:
var collection = mongoDatabase.GetCollection<Order>("your-collection-name");
var filter = Builders<Order>.Filter.Empty;
var order = collection.Find(filter).FirstOrDefault();

关键注意点

  • 字段大小写匹配:MongoDB中的字段是驼峰格式(如goodsList),实体类是帕斯卡格式,需通过[BsonElement]特性或全局配置CamelCaseElementNameConvention来匹配。
  • 字段类型兼容:转换value时要确保类型匹配(如price用AsDecimal而非AsString),避免类型转换异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 13:08:19