Автоматически использовать строки HtmlEncode, когда модель сериализуется с помощью Json.Net.

Есть ли способ настроить Json.Net для автоматического кодирования всех строк, таких как HtmlEncode(myString), при сериализации модели?


person Buda Gavril    schedule 22.05.2017    source источник
comment
Я бы этого не ожидал - я ожидал, что он будет кодировать строки в терминах JSON. Было бы очень странно, если бы он HTML-кодировал контент. Работа сериализатора JSON состоит в том, чтобы получать данные от X до Y в виде JSON... для того, чтобы он выполнял кодирование HTML, это похоже на массовое расширение области видимости.   -  person Jon Skeet    schedule 22.05.2017
comment
Почему бы не создать метод, в котором вы передаете объект для сериализации, и он возвращает результат строки в кодировке html?   -  person user1628733    schedule 22.05.2017
comment
Это то, что вы спросили? кодирование   -  person Artyom    schedule 22.05.2017
comment
@Artyom Да, спасибо, это то, что я искал. Спасибо   -  person Buda Gavril    schedule 22.05.2017


Ответы (3)


Вы можете использовать решение, аналогичное тому, что описано в Выборочное экранирование HTML в строках во время десериализации, с парой незначительных изменений:

  1. Измените HtmlEncodingValueProvider, чтобы применить кодировку в GetValue, а не SetValue (чтобы кодирование выполнялось при сериализации, а не при десериализации).
  2. Измените преобразователь, чтобы применить поставщик значений ко всем строковым свойствам, а не искать атрибут.

Вот как будет выглядеть полученный код:

public class CustomResolver : DefaultContractResolver
{
    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        IList<JsonProperty> props = base.CreateProperties(type, memberSerialization);

        // Attach an HtmlEncodingValueProvider instance to all string properties
        foreach (JsonProperty prop in props.Where(p => p.PropertyType == typeof(string)))
        {
            PropertyInfo pi = type.GetProperty(prop.UnderlyingName);
            if (pi != null)
            {
                prop.ValueProvider = new HtmlEncodingValueProvider(pi);
            }
        }

        return props;
    }

    protected class HtmlEncodingValueProvider : IValueProvider
    {
        PropertyInfo targetProperty;

        public HtmlEncodingValueProvider(PropertyInfo targetProperty)
        {
            this.targetProperty = targetProperty;
        }

        // SetValue gets called by Json.Net during deserialization.
        // The value parameter has the original value read from the JSON;
        // target is the object on which to set the value.
        public void SetValue(object target, object value)
        {
            targetProperty.SetValue(target, (string)value);
        }

        // GetValue is called by Json.Net during serialization.
        // The target parameter has the object from which to read the string;
        // the return value is the string that gets written to the JSON
        public object GetValue(object target)
        {
            string value = (string)targetProperty.GetValue(target);
            return System.Web.HttpUtility.HtmlEncode(value);
        }
    }
}

Используйте пользовательский ContractResolver следующим образом:

var settings = new JsonSerializerSettings
{
    ContractResolver = new CustomResolver(),
    Formatting = Formatting.Indented
};

string json = JsonConvert.SerializeObject(your_object, settings);

Скрипт: https://dotnetfiddle.net/RhFlk8

person Brian Rogers    schedule 22.05.2017
comment
Отличное решение! - person gls123; 11.06.2019

Попробуй это:

var json = JObject.Parse("{'Name':'<script>alert(1);</script>'}");
var serializerSettings = new JsonSerializerSettings()
{
    StringEscapeHandling = StringEscapeHandling.EscapeHtml
};
var result = JsonConvert.SerializeObject(json, serializerSettings);

результат будет:

{"Name":"\u003cscript\u003ealert(1);\u003c/script\u003e"}
person Mohammad Nikravan    schedule 24.01.2018
comment
Это не кодирует строки так же, как @Html.Encode(), но я нашел это полезным для моего варианта использования. - person Kevin Secrist; 14.05.2018
comment
Если ваш экранированный HTML, как указано выше, загружается в контексты eval, такие как функция jQuery.html, скрипт будет выполнен. HTML-кодирование Http Utility лучше. - person gls123; 11.06.2019
comment
Не отвечая на вопрос, но именно то, что мне было нужно :D - person HelloWorld; 14.09.2020

Я нашел очень простой способ сделать это (WebAPI2).

Когда вы устанавливаете свойства объекта, просто закодируйте его ниже.

myObject.encoded_field = HttpUtility.HtmlEncode(ваш_html_контент)

person BenW    schedule 26.06.2018