Home > Blockchain >  JsonConvert DeserializeObject not working as expected
JsonConvert DeserializeObject not working as expected

Time:10-22

Ok so I have these classes to process an Event of an OrderUploadFile creation:

public class ProcessOrderXlsEvent : ProcessFileBaseEvent
{
    public Guid Id { get; set; }
}
public class ProcessFileBaseEvent
{
    public OrderUploadFile? Message { get; set; }
    public DateTime Timestamp { get; set; }
}

I have a class OrderUploadFile that inherits from Entity (which is used by other classes)

public class OrderUploadFile : Entity
{
    public string FileNameOriginal { get; private set; }

    public string ContentType { get; private set; }

    public long ContentLength { get; private set; }

    public OrderUploadFile(
        string fileNameOriginal,
        string contentType,
        long contentLength)
    {
        FileNameOriginal = fileNameOriginal;
        ContentType = contentType;
        ContentLength = contentLength;
    }
}

Entity:

public abstract class Entity
{
    public Guid Id { get; private set; }
    public string CreatedBy { get; set; }
    public DateTime CreatedAt { get; private set; }
    public string? UpdatedBy { get; set; }
    public DateTime? UpdatedAt { get; set; }

    protected Entity()
    {
        Id = Guid.NewGuid();
    }
}

A message comes with this structure:

{
  "Id": "dasadsa-dasda-dasda-42fdsa-1312dswas",
  "Message": {
    "FileNameOriginal": "fileName-etc.xlsm",
    "ContentType": "application/vnd.ms-excel.sheet.macroEnabled.12",
    "ContentLength": 153121,
    "Id": "432424dasdad-fdsfsd312-dsa21-312dsa-ds212",
    "CreatedBy": null,
    "CreatedAt": "0001-01-01T00:00:00",
    "UpdatedBy": null,
    "UpdatedAt": null
  },
  "Timestamp": "2022-10-21T09:25:16.9305165Z"
}

The message, when it arrives, actually has the correct id of the OrderUploadFile class, but when deserialized, this id is not recognized. If I comment out the Entity constructor's Id assignment line to test, the OrderUploadFile's Id is left with an empty Guid (example 0000-0000-0000-etc).

This is the way of deserialization (As MessageBody being the message above):

JsonConvert.DeserializeObject<ProcessOrderXlsEvent>(args.MessageBody);

How can I get the Id inside the message to be correctly assigned to OrderUploadFile? Is it possible to do this even inheriting from Entity?

CodePudding user response:

Your OrderUploadFile instances will never receive the OrderUploadFile/Entity Id's from the json with your current implementation. Why is that so?

To create an OrderUploadFile instance, its constructor has to be used. The constructor itself has no parameter for the Id, so the deserializer cannot pass the respective value from the json data to the constructor.

But could the deserializer not set the respective Id property directly to the value from the json? Well, that property only got a private setter, so by default the deserializer will not attempt to set the value of this property either.

There are a number of different solutions to your problem:

  • Include a parameter for the Id in the OrderUploadFile and Entity constructors. Alternatively to changing the or adding another Entity constructor, the Id property setter could be made protected so the OrderUploadFile constructor would be able to set the Id property directly.
  • Make the Entity.Id setter public.
  • Annotate the Entity.Id property wih Newtonsoft.Json's [JsonProperty] attribute (which tells Newtonsoft.Json to use the setter regardless of its accessibility).
  • Write a custom JsonConverter that "manually" creates and populates OrderUploadFile instances from the json data and sets the Entity.Id property through reflection.
  • Related