Home > Back-end >  ASP.NET Core - Can't serialize JSON for sending to another API
ASP.NET Core - Can't serialize JSON for sending to another API

Time:08-24

Have an ASP.NET Core Web API with some services.

I have a database entity Products:

public class Products
{
    public int ProductId { get; set; }
    public string ProductCode { get; set; }
    public bool InStock { get; set; }
    public DateTime CreateDate { get; set; }
}

and a model class working with Products:

public class ProductModel
{
    public int ProductId { get; set; }
    public string ProductCode { get; set; }
}

public class ProductListModel
{
    [JsonPropertyName("data")]
    public List<ProductModel> ProductList { get; set; }
}

I need to take my products from my database and send them to an external API. But that external API needs JSON format like this:

{
  "data": [
    {
      "ProductId": 1,
      "ProductCode": "000001AD"
    },
    {
      "ProductId": 2,
      "ProductCode": "000001AB"
    },
    {
      "ProductId": 3,
      "ProductCode": "000002AA"
    }
  ]
} 

I'll take data from the database:

var products = _context.Products.Where(x => x.InStock).ToList();

Then I use AutoMapper, but test.data always returns null:

var test = new ProductListModel();
_mapper.Map(products , test.ProductList);

But, if I serialized like this (without AutoMapper):

var products = _context.Products.Where(x => x.InStock).ToList();
var json = JsonConvert.SerializeObject(products );
var model = JsonConvert.DeserializeObject<ProductListModel>(json);

On the last line with the model variable, I get this error:

Newtonsoft.Json.JsonSerializationException: 'Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'MyProject.Test.Models.ProductListModel' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.
To fix this error either change the JSON to a JSON object (e.g. {"name":"value"}) or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array.
Path '', line 1, position 1.'

How can I take records from the database, put them in "data" and not get an error?

Thanks a lot.

CodePudding user response:

Solution: AutoMapper

Your Mapping Configuration / Profile should be as below:

MapperConfiguration _config = new MapperConfiguration(config => 
{
    config.CreateMap<Products, ProductModel>(); 
            
    config.CreateMap<List<Products>, ProductListModel>()
        .ForMember(dest => dest.ProductList, opt => opt.MapFrom(src => src));   
});

Mapping function

var test = new ProductListModel();
_mapper.Map(products, test);

Or

var test = new ProductListModel();
test.ProductProductList = _mapper.Map<List<ProductModel>>(products);

Demo @ .NET Fiddle


Solution: For Newtonsoft.Json Deserialize

products is List<Products> type. When you try to deserialize the JSON, you should deserialize it as the List<ProductListModel> type.

var model = JsonConvert.DeserializeObject<List<ProductListModel>>(json);

Side note

JsonPropertyName attribute is used for System.Text.Json

[JsonPropertyName("data")]

JsonProperty attribute is used for Newtonsoft.Json

[JsonProperty("data")]

CodePudding user response:

you don't need any mapper, just fix your code. You are trying to deserialize List as ProductListModel, but they are very different. try this

var products = _context.Products
                        .Where(x => x.InStock)
                        .Select(x=> new ProductModel {
                               ProductId=x.ProductId,
                               ProductCode=x.ProductCode
                               })
                        .ToList();

ProductListModel productListModel= new ProductListModel { ProductList = products };

var json = JsonConvert.SerializeObject(productListModel);

ProductListModel model = JsonConvert.DeserializeObject<ProductListModel>(json);
  • Related