簡體   English   中英

如何將ViewModel序列化為JSON對象

[英]How can I serialise a ViewModel in to a JSON object

我有一個視圖模型。 該視圖模型具有實現。 實現是ac#類。 c#類具有屬性和屬性。 我想將屬性和屬性序列化為JSON對象。 我不需要任何數據,這是我在JSON對象中所需的驗證詳細信息。 以下是我的視圖模型:

public class CreateProjectViewModel
{
    public SelectList Categories;
    public SelectList Locations;

    public CreateProjectViewModel() { }

    public CreateProjectViewModel(SelectList categories, SelectList locations)
    {
        this.Categories = categories;
        this.Locations = locations; 
    }

    [Required(ErrorMessage = "You must provide a unique name for your project.")]
    [Display(Name = "Project name")]
    [MaxLength(128)]
    public string Name { get; set; }

    [Required(ErrorMessage = "Give a succinct description of the issues your project is designed to address")]
    [Display(Prompt = "E.g Reduce plastic waste and save our oceans!")]
    public string Description { get; set; }
}

使用NewtonSoft

var vm = new CreateProjectViewModel();
string serialized = JsonConvert.SerializeObject(vm);

編輯

您能否擴展答案以包括視圖模型注釋的序列化,例如[Display(Name =“ Project name”)]和[MaxLength(128)]?

換句話說:“我可以序列化應用於屬性的屬性嗎?”

大多數庫中沒有開箱即用的功能。 為此,我們將需要創建自己的自定義轉換器。 幸運的是,NewtonSoft使我們能夠編寫自己的轉換器。 這不是一件小事,但可行。 這是一個自定義轉換器,它將對屬性進行序列化。


定制轉換器

public class KeysJsonConverter<T> : JsonConverter {
   private readonly Type[] _types;

   public KeysJsonConverter(params Type[] types) {
      _types = types;
   }

   public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) {
      JToken t = JToken.FromObject( value );

      if( t.Type != JTokenType.Object ) {
         t.WriteTo( writer );
      }
      else {
         JObject o = ( JObject ) t;
         IList<JProperty> jProperties = o.Properties().ToList();

         PropertyInfo[] viewModelProperties = typeof( T ).GetProperties();
         foreach( var thisVmProperty in viewModelProperties ) {
            object[] thisVmPropertyAttributes = thisVmProperty.GetCustomAttributes( true );
            var jObjectForVmProperty = new JObject();
            var thisProperty = jProperties.Single( x => x.Name == thisVmProperty.Name );
            jObjectForVmProperty.Add( "ActualValue", thisProperty.Value );
            foreach( var thisVmPropertyAttribute in thisVmPropertyAttributes ) {

               if (thisVmPropertyAttribute is MaxLengthAttribute ) {
                     CreateObjectForProperty( thisVmPropertyAttribute as MaxLengthAttribute,
                        jObjectForVmProperty );
               }
               else if (thisVmPropertyAttribute is RequiredAttribute ) {
                     CreateObjectForProperty( thisVmPropertyAttribute as RequiredAttribute,
                        jObjectForVmProperty );
               }
               else if (thisVmPropertyAttribute is DisplayAttribute ) {
                     CreateObjectForProperty( thisVmPropertyAttribute as DisplayAttribute,
                        jObjectForVmProperty );
               }
               else {
                  continue; // Put more else if conditions like above if you want other types
               }     
            }

            thisProperty.Value = jObjectForVmProperty;
         }

         o.WriteTo( writer );
      }
   }

   private void CreateObjectForProperty<TAttribute>(TAttribute attribute, JObject jObjectForVmProperty) 
         where TAttribute : Attribute
   {
      var jObjectForAttriubte = new JObject();

      var max = attribute as TAttribute;
      var maxPropeties = typeof( TAttribute ).GetProperties();
      foreach( var thisProp in maxPropeties ) {
         try {

            jObjectForAttriubte.Add( new JProperty( thisProp.Name, thisProp.GetValue( max ) ) );
         }
         catch( Exception ex) {
            // No need to worry. Fails on complex attribute properties and some other property types. You do not need this.
            // If you do, then you need to take care of it.
         }
      }
      jObjectForVmProperty.Add( typeof( TAttribute ).Name, jObjectForAttriubte );
   }

   public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {
      throw new NotImplementedException( "Unnecessary because CanRead is false. The type will skip the converter." );
   }

   public override bool CanRead
   {
      get { return false; }
   }

   public override bool CanConvert(Type objectType) {
      return _types.Any( t => t == objectType );
   }
}

上面的轉換器是通用的,因此它適用於任何類型。 現在,它將序列化以下屬性: MaxLengthAttributeRequiredAttributeDisplayAttribute 但是要做其他事情是非常容易的:只需創建一個條件,就像我在continue部分中提到的那樣。

該屬性的值存儲在名為ActualValue的屬性中。


用法

var vm = new CreateProjectViewModel() { Description = "My long description",
    Name = "StackOverflow" };
string json = JsonConvert.SerializeObject( vm, Formatting.Indented, 
    new KeysJsonConverter<CreateProjectViewModel>
    ( typeof( CreateProjectViewModel ) ) );

輸出量

這是當我使用CreateProjectViewModel時的輸出:

{
    "Categories": null,
    "Locations": null,
    "Name": {
        "ActualValue": "StackOverflow",
        "RequiredAttribute": {
            "AllowEmptyStrings": false,
            "RequiresValidationContext": false,
            "ErrorMessage": "You must provide a unique name for your project.",
            "ErrorMessageResourceName": null,
            "ErrorMessageResourceType": null
        },
        "DisplayAttribute": {
            "ShortName": null,
            "Name": "Project name",
            "Description": null,
            "Prompt": null,
            "GroupName": null,
            "ResourceType": null
        },
        "MaxLengthAttribute": {
            "Length": 128,
            "RequiresValidationContext": false,
            "ErrorMessage": null,
            "ErrorMessageResourceName": null,
            "ErrorMessageResourceType": null
        }
    },
    "Description": {
        "ActualValue": "My long description",
        "RequiredAttribute": {
            "ErrorMessage": "Give a succinct description of the issues your project is designed to address",
            "AllowEmptyStrings": false,
            "RequiresValidationContext": false,
            "ErrorMessageResourceName": null,
            "ErrorMessageResourceType": null
        },
        "DisplayAttribute": {
            "Name": null,
            "ShortName": null,
            "Description": null,
            "Prompt": "E.g Reduce plastic waste and save our oceans!",
            "GroupName": null,
            "ResourceType": null
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM