2017-01-22 2 views
0

Ich habe ein View-Modell. Dieses Ansichtsmodell hat eine Implementierung. Die Implementierung ist eine C# -Klasse. Die C# -Klasse verfügt über Eigenschaften und Attribute. Ich möchte die Eigenschaften und Attribute in einem JSON-Objekt serialisieren. Ich brauche keine der Daten, es sind die Validierungsdetails, die ich im JSON-Objekt benötige. Das Folgende ist meine Ansicht Modell:Wie kann ich ein ViewModel in ein JSON-Objekt serialisieren

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; } 
} 
+0

Dies ist etwas, das Sie selbst implementieren müssen. Entscheiden Sie zuerst, welche Eigenschaften und Attribute Sie serialisieren möchten und wie der JSON aussehen soll. Verwenden Sie dann die Reflektion, um die Eigenschaften und Attribute zu untersuchen, die Sie interessieren, und generieren Sie Ihr benutzerdefiniertes JSON-Format. – Joe

Antwort

3

Verwendung NewtonSoft:

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

EDIT

Können Sie Ihre Antwort auf umfassen die Serialisierung der View-Modell Anmerkungen erweitern wie [ Anzeige (Name = "Projektname")] und [MaxLength (128)]?

Mit anderen Worten: "Kann ich die an Eigenschaften angelegten Attribute serialisieren?"

Dies ist nicht etwas, das in den meisten Bibliotheken out-of-the-box verfügbar ist. Wir müssen dafür einen eigenen benutzerdefinierten Konverter erstellen. Zum Glück gibt uns NewtonSoft die Möglichkeit, unsere eigenen Konverter zu schreiben. Dieser ist nicht trivial, aber machbar. Hier ist ein benutzerdefinierter Konverter, der die Attribute serialisiert.


Individuelle Converter

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); 
    } 
} 

Der Konverter oben ist generisch, so dass es für jede Art zu arbeiten. Im Moment wird es diese Attribute serialisieren: MaxLengthAttribute, RequiredAttribute, DisplayAttribute. Aber andere zu tun ist super einfach: Erstelle einfach eine andere Bedingung, wie ich im Abschnitt continue kommentiert habe. Der Wert für die Eigenschaft wird in einer Eigenschaft mit der Bezeichnung ActualValue gespeichert.


Nutzungs

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

Ausgabe

Hier ist der Ausgang, wenn ich Ihre CreateProjectViewModel verwendet:

{ 
    "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 
     } 
    } 
} 
+0

Danke. Das ist fantastisch. Könnten Sie Ihre Antwort auf die Serialisierung der Anmerkungen des Ansichtsmodells wie "[Display (Name =" Projektname ")]' und '[MaxLength (128)]' erweitern? – Stewart

+0

@Stewart siehe meine bearbeitete Antwort - das sollte es für Attribute tun. – CodingYoshi

Verwandte Themen