Веб-API: не удалось сериализовать тело ответа для типа контента

Я работаю с ASP.NET MVC 5 Web Api.

У меня есть существующее приложение со многими api. Недавно я реализовал собственный JsonConverter, который будет преобразовывать дату в соответствии с часовым поясом.

public class CustomInfoConverter : JsonConverter
{

    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(CustomType);
    }
    public override bool CanRead
    {
        get
        {
            return false;
        }
    }
    public override bool CanWrite
    {
        get
        {
            return true;
        }
    }
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var customType = (CustomType)value;
        if (customType == null || null== customType.TimeZone) return;
        //DateTime currentDateTime = customType.Date??DateTime.Now;
        DateTime currentDateTime = DateTime.SpecifyKind(customType.Date ?? DateTime.Now, DateTimeKind.Unspecified);

        DateTime userDateTime = TimeZoneInfo.ConvertTimeFromUtc(currentDateTime, customType.TimeZone);
        customType.Date = userDateTime;
        JsonSerializer innerSerializer = new JsonSerializer();
        foreach (var converter in serializer.Converters.Where(c => !(c is CustomInfoConverter)))
        {
            innerSerializer.Converters.Add(converter);
        }
        innerSerializer.Serialize(writer, customType);


    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }


}

После реализации этого настраиваемого JsonConverter все api работают, кроме одного api, который выдает исключение ниже

Вы можете обратиться к этой ссылке. Больше подробностей.

Проблема заключается в том, что в определенных ситуациях вы возвращаетесь из

public class CustomInfoConverter : JsonConverter
{

    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(CustomType);
    }
    public override bool CanRead
    {
        get
        {
            return false;
        }
    }
    public override bool CanWrite
    {
        get
        {
            return true;
        }
    }
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var customType = (CustomType)value;
        if (customType == null || null== customType.TimeZone) return;
        //DateTime currentDateTime = customType.Date??DateTime.Now;
        DateTime currentDateTime = DateTime.SpecifyKind(customType.Date ?? DateTime.Now, DateTimeKind.Unspecified);

        DateTime userDateTime = TimeZoneInfo.ConvertTimeFromUtc(currentDateTime, customType.TimeZone);
        customType.Date = userDateTime;
        JsonSerializer innerSerializer = new JsonSerializer();
        foreach (var converter in serializer.Converters.Where(c => !(c is CustomInfoConverter)))
        {
            innerSerializer.Converters.Add(converter);
        }
        innerSerializer.Serialize(writer, customType);


    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }


}
, ничего не написав, особенно когда _2_:


person Roshan    schedule 06.11.2015    source источник


Ответы (1)


Это приведет к получению недопустимого объекта JSON, поскольку свойство name уже было записано вызывающей стороной, в результате чего:

    var customType = (CustomType)value;
    if (customType == null || null== customType.TimeZone) return;

Попытка сделать это приводит к появлению исключения.

{
    "customType":
}

Вместо этого вам нужно предотвратить сериализацию самого свойства. Однако это невозможно в конвертере, это необходимо сделать в содержащем типе.

Чтобы избежать сериализации свойства с нулевым значением, вы должны установить NullValueHandling = NullValueHandling.Ignore в настройках сериализатора, или на самом свойстве:

Чтобы предотвратить сериализацию вашего свойства, когда его свойство TimeZone имеет значение null, вы должны использовать условную сериализацию свойства путем добавления метода ShouldSerializeXXX() к содержащему типу, где XXX точно соответствует имени вашего свойства:

public class ContainerClass
{
    [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
    public CustomType CustomType { get; set; }
}

{"Сообщение": "Произошла ошибка.", "ExceptionMessage": "Типу 'ObjectContent`1' не удалось сериализовать тело ответа для типа содержимого 'application / json; charset = utf-8'.", "ExceptionType ":" System.InvalidOperationException "," StackTrace ": null," InnerException ": {" Сообщение ":" Произошла ошибка. "," ExceptionMessage ":" Token PropertyName в состоянии Свойство приведет к недопустимому объекту JSON. Путь 'Data.Forms [0]'. "," ExceptionType ":" Newtonsoft.Json.JsonWriterException "," StackTrace ":" в Newtonsoft.Json.JsonWriter.AutoComplete (JsonToken tokenBeingWritten) \ r \ n в Newtonsoft.Json.JsonWriter .InternalWritePropertyName (имя строки) \ r \ n в Newtonsoft.Json.JsonTextWriter.WritePropertyName (имя строки, логическое экранирование) \ r \ n в Newtonsoft.Json.Serialization.JsonProperty.WritePropertyName (писатель JsonWriter) \ r \ n в Newtonsoft. Json.Serialization.JsonSerializerInternalWriter.SerializeObject (писатель JsonWriter, значение объекта, контракт JsonObjectContract, JsonProperty me mber, JsonContainerContract collectionContract, JsonProperty containerProperty) \ r \ n в Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue (JsonWriter writer, значение объекта, JsonContract valueContract, член JsonProperty, контейнер JsonContainersonProperty. Serialization.JsonSerializerInternalWriter.SerializeList (писатель JsonWriter, значения IEnumerable, контракт JsonArrayContract, член JsonProperty, JsonContainerContract collectionContract, JsonProperty containerProperty) \ r \ n в Newtonsoft.Json.SerializationProperty. , JsonContainerContract containerContract, JsonProperty containerProperty) \ r \ n в Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject (писатель JsonWriter, значение объекта, контракт JsonObjectContract, член JsonProperty, J sonContainerContract collectionContract, JsonProperty containerProperty) \ r \ n в Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue (писатель JsonWriter, значение объекта, JsonContract valueContract, член JsonProperty, JsonConract.Contract containerContract, JsonProperty контейнер \. JsonSerializerInternalWriter.SerializeObject (писатель JsonWriter, значение объекта, контракт JsonObjectContract, член JsonProperty, контракт collectionContract JsonContainerContract, JsonProperty containerProperty) \ r \ n в Newtonsoft. Json.Serialization.JsonSerializerInternalWriter.SerializeValue (писатель JsonWriter, значение объекта, JsonContract valueContract, член JsonProperty, JsonContainerContract containerContract, JsonProperty containerProperty) \ r \ n в Newtonsoft.Json.Serialization.JsonSriterializer (значение объекта \ r \ n в Newtonsoft.Json.JsonSerializer.SerializeInternal (JsonWriter jsonWriter, значение объекта, тип objectType) \ r \ n в Newtonsoft.Json.JsonSerializer.Serialize (JsonWriter jsonWriter, значение объекта) \ r \ n в System.Net. Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStream (тип типа, значение объекта, поток writeStream, эффективное кодирование кодирования) \ r \ n в System.Net.Http.Formatting.JsonMediaTypeFormatter.WriteToStream (тип типа, значение кодирования объекта, эффективное значение кодирования потока, поток writeEncoding) r \ n в System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStream (тип типа, значение объекта, поток writeStream, HttpContent content) \ r \ n в System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStreamAsync (Type type, Object value, Stream writeStream, HttpContent content, TransportContext transportContext, CancellationToken cancellationToken) \ r \ n --- Конец трассировки стека из предыдущее место, где было сгенерировано исключение --- \ r \ n в System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (задача задачи) \ r \ n в System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (задача задачи) \ r \ n в System.Runtime.CompilerServices.TaskAwaiter.GetResult () \ r \ n в System.Web.Http.WebHost.HttpControllerHandler.d__1b.MoveNext () "}}

public class ContainerClass
{
    public CustomType CustomType { get; set; }

    public bool ShouldSerializeCustomType()
    {
        return CustomType != null && CustomType.TimeZone != null;
    }
}
person dbc    schedule 06.11.2015