Как можно исключить некоторые открытые свойства из сериализации в JsonResult? - PullRequest
8 голосов
/ 15 сентября 2009

У меня есть пользовательская модель представления, которая сериализована с использованием JsonResult. ViewModel имеет некоторые свойства, которые должны быть открытыми, но в то же время эти свойства не должны быть видны в итоговом выводе Json.

Я уже пытался использовать атрибут [NonSerialized], но, похоже, это не имело никакого эффекта.

Есть ли простой способ сделать это? Или я должен был бы кодировать свой собственный тип результата (в этом случае я, вероятно, не буду беспокоиться)?

Ответы [ 6 ]

26 голосов
/ 08 октября 2009

Вы можете поместить атрибут [ScriptIgnore] в элементы, которые не должны быть сериализованы. См. Пример ScriptIgnoreAttribute в MSDN .

2 голосов
/ 31 марта 2014

Просто создайте интерфейс для возврата вместо класса.

public interface IMyViewModel {
   string MyPublicProperty { get; set; }
}

Затем создайте класс, который наследует интерфейс

public class MyViewModel : IMyViewModel {
   public string MyPublicProperty { get; set; }
   public string MyNotSoPublicProperty { get; set; }
}

И вернуть интерфейс, а не класс, в действии контроллера

public JsonResult MyJson(){
    IMyViewModel model = new MyViewModel();
    return Json(model);
}

И полученный JSON будет

{
    'MyPublicProperty': ''
}

Одна из проблем сценариев на стороне клиента заключается в том, что если вы меняете классы, вы не представляете, разрушаете ли вы реализацию на стороне клиента или нет. Если вы используете типы интерфейсов в вашем JSON, вы понимаете, что если вы меняете интерфейс, вы делаете что-то, что потенциально может убить реализацию на стороне клиента. И это также избавляет вас от тщательной проверки на стороне клиента, если вы изменяете что-то, что НЕ находится в интерфейсе (таким образом, не сериализуется).

Кроме того, во многих случаях ваши ViewModels могут содержать большие коллекции или сложные типы, которые вы не обязательно хотите выводить клиенту. Это может занять много времени для сериализации или раскрытия информации, которая просто не принадлежит клиентскому коду. Использование интерфейсов сделает более прозрачным понимание того, что происходит в выводе.

Кроме того, использование таких атрибутов, как [ScriptIgnore] в свойстве, применимо только к конкретному сценарию (сериализация JavaScript), что заставляет вас столкнуться с точно такой же проблемой, если вы позже сериализуетесь в XML, например. Это излишне засоряет ваши модели представления множеством атрибутов. Сколько из них вы действительно хотите там? Использование интерфейсов применимо везде, и никакой модели представления не нужно засорять дополнительными атрибутами.

2 голосов
/ 16 сентября 2009

Взгляните на JSON.NET от Джеймса Ньютона-Кинга. Он будет делать то, что вы ищете.

1 голос
/ 16 сентября 2009

Расширьте класс JavaScriptConverter, чтобы не включать свойства с NonSerializedAttribute. Затем вы можете создать пользовательский ActionResult, который использует ваш JavaScriptConverter для сериализации объекта.

Это создает надежный и тестируемый класс без необходимости (повторного) создания классов-оболочек или использования анонимных объектов.

0 голосов
/ 15 сентября 2009

Вы можете создать класс-оболочку, который предоставляет только те свойства, которые вам нужны в JsonResult. В приведенном ниже примере у Cow есть 2 свойства - «Leg» и «Moo». Предположим, вы хотите выставить «Leg» только как собственность. Тогда

Dim CW as CowWrapper = Новый CowWrapper (c)

вернет класс-оболочку, который выставляет только «Leg». Это также полезно для таких вещей, как DataGridView, если вы хотите отобразить только некоторое подмножество свойств.

Корова общественного класса

Открытое свойство ReadOnly Leg () в виде строки

   get

      return "leg"

   end get

конечная недвижимость

Открытое свойство ReadOnly Moo () в виде строки

   get

      return "moo"

   end get

конечная недвижимость

конечный класс

Public Class CowWrapper

Private m_cow as Cow = Nothing

Public Sub New(ByVal cow as Cow)

   m_cow = cow

end Sub


    m_cow = cow

Public ReadOnly Property Leg () в виде строки

   get

      return m_cow.Leg()

   end get

конечная недвижимость

конец класса

0 голосов
/ 15 сентября 2009

Не совсем тот ответ, который вы ищете, но вы можете обмануть Json(), используя следующий код и анонимные классы:

MyModel model = ...;
return Json(new MyModel {model.Prop1, model.Prop2});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...