2016-11-09 3 views
0

Я пытаюсь передать объект в приложение web api. При сериализации объекта он преобразует его в строку json. Но на стороне приложения app api он получает параметр объекта как объект JObject. Этот кодовый блок из приложения web api;Преобразование JObject в анонимный объект

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

Этот код генерирует JObject, но мне нужен анонимный объект. Проект Web api не знает типы. Любые типы объектов могут быть получены.

Мне нужен такой объект.

Тип ExpandoObject не соответствует моим требованиям, поэтому преобразование в динамический тип для меня не является решением.

+0

Telerik report objectdatasource нуждается в реальном объекте, так что я пытаюсь решить эту проблему. – Baran

+1

Это будет довольно сложно. Вы можете начать с http://stackoverflow.com/questions/3862226/how-to-create-dynamically-a-class-in-c или http://stackoverflow.com/questions/606104/how-to-create- linq-expression-tree-to-select-an-anonymous-type/28140345 # 28140345 – dbc

+1

Согласно [документации] (http://docs.telerik.com/reporting/objectdatasource), Telerik Reporting ObjectDataSource может связываться с такими вещами, как 'DataSet',' DataTable', 'IListSource' и' IEnumerable' и другие. Таким образом, у вас есть некоторые параметры, кроме попыток создания анонимных объектов. –

ответ

0

объекты JSon не может быть полностью сериализованными как объект. Если вы используете Newtonsoft, он преобразует неизвестный тип в JObject. В этой задаче мы попытались создать неизвестный тип во время выполнения. Чтобы сделать это на стороне wep api, мы должны передать деталь типа в приложение web api. Json.NET Schema библиотека может сериализовать тип в строку. Этот метод помогает нам передать схему неизвестных типов в приложение web api. С веб-страницы api необходимы два параметра. Первый параметр - строка схемы json, а вторая - строка данных json. На этом этапе с помощью строки json schema мы можем сгенерировать этот тип во время выполнения с помощью библиотеки Reflection. Вот класс C#. Но он не работает для списков или массивов. В будущем я смогу его развить.

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

Метод Convert помогает сгенерировать объект из json-данных с помощью схемы json. Просто используя команду Newtonsoft.Json.JsonConvert.DeserializeObject (json, type), мы можем получить реальный объект. Он работает с Telerik Reporting как объект ObjectDataSource.

2

Ближайший я могу найти с помощью десериализации Newtonsoft является

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

См Deserialize json object into dynamic object using Json.net

Приветствия

+0

Извините, динамический тип для меня не является решением. – Baran

+0

Я действительно верю, что вам нужно будет определить класс для ваших объектов JSON, создать динамический объект или использовать динамические объекты. Возможно, я ошибаюсь, но я не думаю, что есть полезный четвертый вариант. – JasonX

Смежные вопросы