skip to Main Content

I’m using c# to read data from MongoDb and I’ve run into a situation where the data for one of my keys: GoodsList is being read in this form:

"goodsList": [
      [
        {
          "name": "name",
          "value": "testName"
        },
        {
          "name": "price",
          "value": 32
        },
        {
          "name": "number",
          "value": 1
        },
        {
          "name": "id",
          "value": 68345
        },
        {
          "name": "cate_id",
          "value": 6208
        },
        {
          "name": "image",
          "value": "/testimg.png"
        },
        {
          "name": "use_property",
          "value": 1
        },
        {
          "name": "props_text",
          "value": "standardtext,standardtext2"
        },
        {
          "name": "props",
          "value": [
            582,
            585
          ]
        }
      ]
    ]


But I don’t want this, I want it to be read in this format below:

"StatusText": "Finished",
  "GoodsList": [
    {
      "name": "testName",
      "price": 32,
      "number": 1,
      "id": 68345,
      "cate_id": 6208,
      "image": "/testimg.png",
      "use_property": 1,
      "props_text": "standardtext,standardtext2",
      "props": [
        582,
        585
      ]
    }
  ],
  "Notes": "this.form.remark",

How can I set the correct format for reading? I’ve tried reading it as BsonArray or BsonDocument or directly as an entity class (GoodsList in entity class as BsonArray or BsonDocument), but it doesn’t work, either I get a conversion error or the result is still the same.

2

Answers


  1. As mentioned in the comment, you should create your own model classes, same goes for GoodsList.

    When you are using BsonArray/BsonDocument and serialize the result, it will show the objects containing the Key and Value properties.

    Your model classes should be as below:

    using MongoDB.Bson.Serialization.Attributes;
    
    [BsonNoId]
    public class Goods
    {
        [BsonElement("name")]
        public string Name { get; set; }
    
        [BsonElement("price")]
        public int Price { get; set; }
    
        [BsonElement("number")]
        public int Number { get; set; }
    
        [BsonElement("id")]
        public int Id { get; set; }
    
        [BsonElement("cate_id")]
        public int CateId { get; set; }
    
        [BsonElement("image")]
        public string Image { get; set; }
    
        [BsonElement("use_property")]
        public int UseProperty { get; set; }
    
        [BsonElement("props_text")]
        public string PropsText { get; set; }
    
        [BsonElement("props")]
        public List<int> Props { get; set; }
    }
    
    public class Root
    {
        public ObjectId Id { get; set; }
    
        [BsonElement("StatusText")]
        public string StatusText { get; set; }
    
        [BsonElement("GoodsList")]
        public List<Goods> GoodsList { get; set; }
    
        [BsonElement("Notes")]
        public string Notes { get; set; }
    }
    
    IMongoDatabase db = /* IMongoDatabase instance */;
    IMongoCollection<Root> collection = db.GetCollection<Root>("<collection name>");
    
    var result = collection.Find(/* Filter criteria */)
        .ToList();
    
    Login or Signup to reply.
  2. The schema of the document is not very easy to deserialize with C#. However, you can create a custom serializer that retrieves the values. I assume you have a POCO structure similar to the following:

    [BsonIgnoreExtraElements]
    public class GoodsContainerDocument
    {
        [BsonRepresentation(BsonType.ObjectId)]
        public string Id { get; set; }
    
        [BsonElement("goodsList")]
        public IList<GoodsItem> Goods { get; set; }
    }
    
    public class GoodsItem
    {
        public string Name { get; set; }
        public int Price { get; set; }
        public int Number { get; set; }
    
        // Other properties omitted for brevity
    }
    

    You can implement a custom serializer that deserializes the single GoodsList objects like this:

    public class GoodsItemSerializer : SerializerBase<GoodsItem>
    {
        public override GoodsItem Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
        {
            if (context.Reader.CurrentBsonType != BsonType.Array)
                throw new InvalidOperationException();
    
            var goodsItem = new GoodsItem();
            var arrayOfProps = ((IList<object>)context.DynamicArraySerializer.Deserialize(context)).OfType<IDictionary<string, object>>().ToArray();
    
            foreach (var dict in arrayOfProps)
            {
                //var dict = new Dictionary<string, object>(prop);
                switch (dict["name"].ToString())
                {
                    case "name":
                        goodsItem.Name = dict["value"].ToString();
                        break;
                    case "number":
                        goodsItem.Number = Convert.ToInt32(dict["value"]);
                        break;
                    case "price":
                        goodsItem.Price = Convert.ToInt32(dict["value"]);
                        break;
                    // ...deserialize other properties as required
                }
            }
    
            return goodsItem;
        }
    }
    

    Above code uses a DynamicArrayDeserializer to read the array that contains the properties of a GoodsList object. It then iterates over the array items and assigns the corresponding properties. At the end, the constructed GoodsList object is returned.

    You either need to register the serializer globally or by using an attribute like this:

    [BsonSerializer(typeof(GoodsItemSerializer))]
    public class GoodsItem
    {
        // ...
    }
    

    When reading the documents from the database, the serializer is used; the goodsList property that holds an array of arrays is deserialized into an IList<GoodsItem>.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search