2016-11-09 3 views
0

Ich versuche, ein Objekt in eine Web-API-Anwendung zu übergeben. Beim Serialisieren des Objekts wird es in eine JSON-Zeichenfolge konvertiert. Aber auf der Seite der wep-API-Anwendung erhält es den Objektparameter als JObject. Dieser Codeblock stammt aus der Web-API-Anwendung;Convert JObject an anonymes Objekt

//Read web api body content into a string variable 
var resultStr = Request.Content.ReadAsStringAsync().Result; 
//Convert json string to object with Newtonsoft 
var obj = Newtonsoft.Json.JsonConvert.DeserializeObject<object>(resultStr); 

Dieser Code erzeugt ein JObject, aber ich brauche ein anonymes Objekt. Web-API-Projekt kennt die Typen nicht. Alle Objekttypen können empfangen werden.

Ich brauche ein Objekt wie dieses.

object anonyObj = new { Prop1 = "Lorem" }; 

Der ExpandoObject-Typ entspricht nicht meinen Anforderungen, daher ist die Konvertierung zu einem dynamischen Typ keine Lösung für mich.

+0

Telerik Berichterstattung Objektdatasource benötigt ein reales Objekt, so dass ich versuche, dieses Problem zu lösen. – Baran

+1

Das wird ziemlich komplex sein. Sie können mit http://stackoverflow.com/questions/3862226/how-to-create-dynamically-a-class-in-c oder http://stackoverflow.com/questions/606104/how-to-create- beginnen. linq-expression-tree-to-select-an-anonymous-type/28140345 # 28140345 – dbc

+1

Laut der Dokumentation (http://docs.telerik.com/reporting/objectdatasource) kann Telerik Reporting ObjectDataSource an Dinge wie binden "DataSet", "DataTable", "IListSource" und "IEnumerable", unter anderem. Sie haben also andere Möglichkeiten, als anonyme Objekte zu erstellen. –

Antwort

0

Json Objekte nicht vollständig serialisiert werden kann als ein Objekt finden. Wenn Sie Newtonsoft verwenden, konvertiert es den unbekannten Typ in ein JObject. In diesem Problem haben wir versucht, einen unbekannten Typ zur Laufzeit zu erstellen. Um dies auf der wep-API-Seite zu tun, müssen wir das Typendetail in die Web-API-Anwendung übergeben. Json.NET Schema Bibliothek kann einen Typ zu einer Zeichenfolge serialisieren. Diese Methode hilft uns, das Schema der unbekannten Typen an die Web-API-Anwendung zu übergeben. Von der Web API Seite werden zwei Parameter benötigt. Der erste Parameter ist der JSON-Schema-String und der zweite ist der JSON-Daten-String. An dieser Stelle können wir diesen Typ mithilfe der json schema string zur Laufzeit mithilfe der Reflection-Bibliothek generieren. Hier ist die C# -Klasse. Aber es funktioniert nicht für Listen oder Arrays. In Zukunft kann ich es entwickeln.

public class ObjectConverter 
{ 
    public static object Convert(string json, JSchema schema) 
    { 
     var type = CreateType(schema); 
     var destObject = Newtonsoft.Json.JsonConvert.DeserializeObject(json, type); 
     return destObject; 
    } 

    private static Type CreateType(JSchema schema) 
    { 
     Type result = null; 
     var typeBuilder = GetTypeBuilder(Guid.NewGuid().ToString()); 
     foreach (var item in schema.Properties) 
     { 
      if (item.Value.Type == (Newtonsoft.Json.Schema.JSchemaType.Object | Newtonsoft.Json.Schema.JSchemaType.Null)) 
      { 
       Type type = CreateType(item.Value); 
       if (item.Value.Type != null) 
       { 
        CreateProperty(typeBuilder, item.Key, type); 
       } 
      } 
      else 
      { 
       if (item.Value.Type != null) 
       { 
        CreateProperty(typeBuilder, item.Key, ConvertType(item.Value.Type.Value)); 
       } 
      } 
     } 

     result = typeBuilder.CreateType(); 
     return result; 
    } 

    private static Type ConvertType(JSchemaType source) 
    { 
     Type result = null; 
     switch (source) 
     { 
      case JSchemaType.None: 

       break; 
      case JSchemaType.String: 
       result = typeof(string); 
       break; 
      case JSchemaType.Number: 
       result = typeof(float); 
       break; 
      case JSchemaType.Integer: 
       result = typeof(int); 
       break; 
      case JSchemaType.Boolean: 
       result = typeof(bool); 
       break; 
      case JSchemaType.Object: 
       result = typeof(object); 
       break; 
      case JSchemaType.Array: 
       result = typeof(Array); 
       break; 
      case JSchemaType.Null: 
       result = typeof(Nullable); 
       break; 
      case Newtonsoft.Json.Schema.JSchemaType.String | Newtonsoft.Json.Schema.JSchemaType.Null: 
       result = typeof(string); 
       break; 
      default: 
       break; 
     } 
     return result; 
    } 

    private static TypeBuilder GetTypeBuilder(string typeSignature) 
    { 
     var an = new AssemblyName(typeSignature); 
     AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run); 
     ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule"); 
     TypeBuilder tb = moduleBuilder.DefineType(typeSignature, 
       TypeAttributes.Public | 
       TypeAttributes.Class | 
       TypeAttributes.AutoClass | 
       TypeAttributes.AnsiClass | 
       TypeAttributes.BeforeFieldInit | 
       TypeAttributes.AutoLayout, 
       null); 
     return tb; 
    } 

    private static void CreateProperty(TypeBuilder tb, string propertyName, Type propertyType) 
    { 
     FieldBuilder fieldBuilder = tb.DefineField("_" + propertyName, propertyType, FieldAttributes.Private); 

     PropertyBuilder propertyBuilder = tb.DefineProperty(propertyName, PropertyAttributes.HasDefault, propertyType, null); 
     MethodBuilder getPropMthdBldr = tb.DefineMethod("get_" + propertyName, MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, propertyType, Type.EmptyTypes); 
     ILGenerator getIl = getPropMthdBldr.GetILGenerator(); 

     getIl.Emit(OpCodes.Ldarg_0); 
     getIl.Emit(OpCodes.Ldfld, fieldBuilder); 
     getIl.Emit(OpCodes.Ret); 

     MethodBuilder setPropMthdBldr = 
      tb.DefineMethod("set_" + propertyName, 
       MethodAttributes.Public | 
       MethodAttributes.SpecialName | 
       MethodAttributes.HideBySig, 
       null, new[] { propertyType }); 

     ILGenerator setIl = setPropMthdBldr.GetILGenerator(); 
     Label modifyProperty = setIl.DefineLabel(); 
     Label exitSet = setIl.DefineLabel(); 

     setIl.MarkLabel(modifyProperty); 
     setIl.Emit(OpCodes.Ldarg_0); 
     setIl.Emit(OpCodes.Ldarg_1); 
     setIl.Emit(OpCodes.Stfld, fieldBuilder); 

     setIl.Emit(OpCodes.Nop); 
     setIl.MarkLabel(exitSet); 
     setIl.Emit(OpCodes.Ret); 

     propertyBuilder.SetGetMethod(getPropMthdBldr); 
     propertyBuilder.SetSetMethod(setPropMthdBldr); 
    } 
} 

Die Convert-Methode hilft durch die Hilfe von json Schema-Objekt von JSON-Daten zu erzeugen. Mit dem Befehl Newtonsoft.Json.JsonConvert.DeserializeObject (json, type) können wir ein reales Objekt erhalten. Es funktioniert mit Telerik Reporting als ObjectDataSource.

2

Der nächstgelegene ich Newtonsoft der Deserializer mit ist

dynamic d = JObject.Parse("{a:1000, b:'c', d: [1,2,3]}"); 

Siehe Deserialize json object into dynamic object using Json.net

Prost

+0

Sorry, dynamischer Typ ist keine Lösung für mich. – Baran

+0

Ich glaube, Sie müssen entweder eine Klasse für Ihre JSON-Objekte definieren, Ihre Objektklasse dynamisch erstellen oder dynamische Objekte verwenden. Ich könnte mich irren, aber ich denke nicht, dass es eine nützliche vierte Option gibt. – JasonX