我正在尝试将对象传递到web api应用程序中。在序列化对象时,它将其转换为json字符串。但是在wep api应用程序端,它将对象参数作为JObject获取。 此代码块来自web api应用程序;
//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项目不知道类型。可以接收任何对象类型。
我需要这样的物体。
object anonyObj = new { Prop1 = "Lorem" };
ExpandoObject类型不符合我的要求,因此转换为动态类型对我来说不是解决方案。
答案 0 :(得分:2)
我能找到的最接近使用Newtonsoft的反序列化器的是
dynamic d = JObject.Parse("{a:1000, b:'c', d: [1,2,3]}");
请参阅Deserialize json object into dynamic object using Json.net
干杯
答案 1 :(得分:0)
Json对象无法完全序列化为对象。如果您使用的是Newtonsoft,它会将未知类型转换为JObject。在这个问题中,我们尝试在运行时创建未知类型。为了在wep api端执行此操作,我们必须将类型详细信息传递到web api应用程序中。 Json.NET Schema库可以将Type序列化为字符串。此方法可帮助我们将未知类型的架构传递给Web api应用程序。从web api方面需要两个参数。第一个参数是json模式字符串,第二个参数是json数据字符串。此时,借助json模式字符串,我们可以使用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 schema的帮助下从json数据生成对象。只需使用Newtonsoft.Json.JsonConvert.DeserializeObject(json,type)命令,我们就可以得到一个真实的对象。它与Telerik Reporting一起用作ObjectDataSource。
答案 2 :(得分:0)
自从JsonConvert.DeserializeAnonymousType现在存在以来,现在的对话可能太旧而无用,但是专门针对JObject看了这篇文章之后,我想到了一个稍微简单的选项,以后有人可能会想用它:)
我在下面创建了扩展方法,该方法只包装了标准的JObject.ToObject方法。
public static T ToAnonymousType<T>(this JObject source, T destinationType)
{
return source.ToObject<T>();
}
然后可以这样使用:
JObject myJObject = new JObject(); // Something more exciting probably happens here
var myAnonymousObject = myJObject.ToAnonymousType(new { Id = default(int), Name = default(string) });