Search code examples
c#json.netazure-functions.net-6.0

Is it possible to set custom contract resolver for automatic json serialization in c#?


I Have an Azure function, which is triggered by http requests. In the function I get data from soap web service in xml format, which has different property names compared to the class that I created for storing that data. Because of that I specified JsonProperty Names for class properties, however I want my class to be serialized with class property names and not json property names. For that I created Custom Contract Resolver, but I don't know how to specify that contract resolver for automatic serializations (by this I mean when data is automatically serialized for http response).

my class:

public class WaybillHeader
{
    [JsonProperty(PropertyName = "ID")]
    public int Id { get; set; }

    [JsonProperty(PropertyName = "TYPE")]
    public int Type { get; set; }

    [JsonProperty(PropertyName = "CREATE_DATE")]
    public DateTime CreateDateTime { get; set; }

    [JsonProperty(PropertyName = "BUYER_TIN")]
    public string BuyerTin { get; set; } = default!;

    [JsonProperty(PropertyName = "BUYER_NAME")]
    public string BuyerName { get; set; } = default!;

    [JsonProperty(PropertyName = "START_ADDRESS")]
    public string StartAddress { get; set; } = default!;

    [JsonProperty(PropertyName = "END_ADDRESS")]
    public string EndAddress { get; set; } = default!;

    [JsonProperty(PropertyName = "DRIVER_TIN")]
    public string DriverTin { get; set; } = default!;

    [JsonProperty(PropertyName = "DRIVER_NAME")]
    public string DriverName { get; set; } = default!;

    [JsonProperty(PropertyName = "TRANSPORT_COAST")]
    public decimal TransportationCost { get; set; }

    [JsonProperty(PropertyName = "DELIVERY_DATE")]
    public DateTime DeliveryDateTime { get; set; }

    [JsonProperty(PropertyName = "STATUS")]
    public int Status { get; set; }

    [JsonProperty(PropertyName = "ACTIVATE_DATE")]
    public DateTime ActivationDateTime { get; set; }

    [JsonProperty(PropertyName = "FULL_AMOUNT")]
    public decimal FullAmount { get; set; }

    [JsonProperty(PropertyName = "CAR_NUMBER")]
    public string CarNumber { get; set; } = default!;

    [JsonProperty(PropertyName = "WAYBILL_NUMBER")]
    public string WaybillNumber { get; set; } = default!;

    [JsonProperty(PropertyName = "CLOSE_DATE")]
    public DateTime CloseDateTime { get; set; }

    [JsonProperty(PropertyName = "S_USER_ID")]
    public string ServiceUserId { get; set; }

    [JsonProperty(PropertyName = "BEGIN_DATE")]
    public DateTime BeginDateTime { get; set; }

    [JsonProperty(PropertyName = "IS_CONFIRMED")]
    [JsonConverter(typeof(StrToBoolConverter))]
    public bool IsConfirmed { get; set; }

    [JsonProperty(PropertyName = "INVOICE_ID")]
    public int InvoiceId { get; set; }

    [JsonProperty(PropertyName = "IS_CORRECTED")]
    [JsonConverter(typeof(StrToBoolConverter))]
    public bool IsCorrected { get; set; }

    [JsonProperty(PropertyName = "BUYER_ST")]
    public int BuyerStatus { get; set; }
}

Custom Contract Resolver:

public class CustomContractResolver : DefaultContractResolver
{
    protected override JsonProperty CreateProperty(MemberInfo member, 
    MemberSerialization memberSerialization)
    {
        var property = 
        base.CreateProperty(member,memberSerialization);

        property.PropertyName = member.Name;
    
        return property;
    }
}

Edit:

I have custom converter to turn "0" and "1" to bool values and what I tried (and it worked but I don't think it's a proper solution) is that I supplied CustomContractResolver to serializer in WriteJson like this:

public class StrToBoolConverter : JsonConverter<bool>
{
    public override void WriteJson(JsonWriter writer, bool value, 
    JsonSerializer serializer)
    {
        serializer.ContractResolver = new CustomContractResolver();
        writer.WriteValue(value);
    }

    public override bool ReadJson(JsonReader reader, Type objectType,             
    bool existingValue, bool hasExistingValue, JsonSerializer 
    serializer)
    {
        if (reader.Value == null)
            return false;

        if (reader.ValueType != typeof(string))
            return false;

        return reader.Value.ToString() switch
        {
            "0" => false,
            "1" => true,
            _ => false
        };
    }
}

this solution worked for every serialized WaybillHeader value except the first one


Solution

  • I would remove all JsonProperty attributes from the c# properties and create a constructor for deserialization

    public class WaybillHeader
    {
        public int Id { get; set; }
    
        public int Type { get; set; }
    
        [JsonProperty(PropertyName = "CreateDateTime")] // You can remove it,
                                                   // or give the name for serialization 
                                                  // if you need a different one
        public DateTime CreateDateTime { get; set; }
    
        .....
    
         [Newtonsoft.Json.JsonConstructor]
        public class WaybillHeader(int ID, int TYPE, DateTime CREATE_DATE, ...)
       {
            Id=ID;
            Type=TYPE;
            CreateDateTime=CREATE_DATE;
            .....
        }
     
    }