怎样js创建匿名对象一个可序列化的匿名类

首先让我们看一个例子, 假设我们并没有Person类, 并且我们关心的属性只有Name和Age. 下面的代码演示了我们如何在没有声明类型的情况下来构建一个对象的:
&& 1: var tom = new { Name = Tom, Age = 4 };&& 2: var holly = new { Name = Holly, Age = 31 };&& 3: var jon = new { Name = Jon, Age = 31 };&& 4: Console.WriteLine({0} is {1} years old, jon.Name, jon.Age);
可以看到, 初始化一个匿名类与我们之前提到的对象初始化器非常相似&&区别仅仅是在new和开始的大括号之间的类型名称没有了. 我们正在使用隐式的局部变量, 因为这是我们的唯一选择&&我们没有任何的类型名可以用于声明该变量. 从上面的最后一行代码你可以看到, 类型用于Name和Age属性, 他们可以被读取并且其值就是在隐式类型初始化器中被赋予的值, 因此, 该输出将会是Jon is 31 years old. 属性将会有与初始化器内的表达式一样的类型&&Name是string类型, Age是int类型. 和对象初始化器一样的是, 方法和构造器也可以被用于隐式对象初始化器中, 用于做任何你想做的是事情.
现在你知道为什么隐式类型数组为什么这么重要了. 假设我们想创建包含整个家庭成员的数组, 然后迭代算出总的年龄. 以下的代码将会完成这个工作&&同时也演示了其他一些有趣的关于匿名类型的特性.
&& 1: var family = new[]&& 2: {&& 3:&&&& new { Name = Holly, Age = 31 },&& 4:&&&& new { Name = Jon, Age = 31 },&& 5:&&&& new { Name = Tom, Age = 4 },&& 6:&&&& new { Name = Robin, Age = 1 },&& 7:&&&& new { Name = William, Age = 1 }&& 8: };&& 9: int totalAge = 0;& 10: foreach (var person in family)& 11: {& 12:&&&& totalAge += person.A& 13: }& 14: Console.WriteLine(Total age: {0}, totalAge);
从前面了解过的隐式类型数组来看, 我们可以推论出一个重要的事情: 所有的家庭成员类型都是一样的. 因为如果他们使用匿名类型初始化器创建的都是一个新的类型, 那么明显数组类型不可能被正确的声明. 在一个给定的Assembly中, 如果两个匿名类型拥有同样数量的属性, 并且他们有相同的名字和类型, 以及相同的出现顺序, 那么编译器将会把他们当成同一个类型. 换句话说, 如果我们把其中一个的Name和Age属性调换一下, 编译器将会生成一个新的匿名类型&&同样的,如果我们在新行中引入一个而外的属性, 或者使用long类型代替Age的int类型, 这些统统会导致编译器生成一个新的匿名类型.
实现细节:如果你曾经看过匿名类的IL代码, 你应该知道即使两个匿名对象初始化器拥有同样的属性名和出现出现, 但却使用不同的类型, 那么编译器会生成两个不同的类型, 而它们实际上是通过一个单独的泛型类来生成的. 该泛型类是参数化的, 但其封闭的构造类型将会因为给与不同初始化器的类型参数不同而不同.
我们可以使用foreach表达式应用于上述的数组, 就像我们用于集合中的一样. 类型是由编译器推断的, person的类型也就是数组的类型. 再次提一下, 我们可以将同样的变量用于不同的实例中, 因为它们全部都拥有相同的类型.
上述的代码同样验证了Age属性是强类型的int, 否则我们试图计算age总和将会导致错误. 编译器了解匿名类型, VS2008更是通过tooltip的方式提供更多的信息. 现在我们已经了解了足够的关于匿名类型信息, 接下来让我们看看编译器实际上为我们做的工作.
匿名类型的成员
匿名类型是由编译器创建并其包含在编译后的Assembly当中, 其方式与匿名方法和iterator block的创建方式是一致的. CRL把它们都当成普通的类型, 实际上他们就是普通的类型&&如果你将其从匿名类型更改成为一个普通类型, 并且手工编写所有行为的代码, 我们不会看到有任何的改变. 匿名类型包含以下的成员:
一个负责所有初始化值的构造器, 其参数将会是与匿名对象初始化器当中出现的顺序和类型一致, 同样名称也是一样的. 公共只读的属性 私有的只读字段, 用于支持属性 重载了Equals, GetHashCode和ToString 这就是全部了, 没有实现任何借口, 没有克隆和序列化能力&&仅仅是一个构造器, 一些属性和几个来自于object的平常的方法.
构造器和属性完成都是一些显而易见的事情. 两个来自于相同匿名类型的实施是否相等, 通过轮流比较所有属性类型的Equals方法来决定.hash代码生成也是一类似的, 通过调用每个属性的GetHashCode然后再合并结果. 将多个hash code合并成为一个组合, 其方法并没有被指定, 因此你不能在你的代码中依靠它&&你唯一有信心的就是, 两个相等的对象实例必然返回相同的hash值, 而两个不等的实例可能会返回不等的hash值. 当然所有这些也只有当属性类型实现的GetHashCode和Equals也遵循常规规则的时候才有效.
注意因为属性是只读的, 因此匿名类是不可变的, 因此属性的类型也是不可变的. 由于这个不可变性, 你不用担心属性在赋值后会被改变, 跨线程自然也没有问题.
发散性初始化器(projection initializers)
目前我们看到的匿名对象初始化器中我们一直使用简单的name / value对&&Name=Jon, Age=31, 虽然有时候我们确实是这么做, 但是更多时候在真实的编程中, 我们可能会从一个已有的对象中来拷贝属性值. 有时我们会通过一些方式来读取值, 不过更经常的是拷贝就足够了.
没有LINQ, 要给出令人信服的例子有点困难, 不过让我们回到我们的Person类, 假设我们有一个很好的理由我们想将一个Person实例的集合转换到另外一个类似的集合, 其元素包含有一个name和一个flag指示该person是否是一个成年人. 给定一个合适的变量, 我们可以使用下面的代码:
&& 1: new { Name = person.Name, IsAdult = (person.Age &= 18) }
该代码当然能够工作, 如果仅仅是设置一个单一的name属性使用此方法当然还不算笨拙&&但如果你要拷贝很多的属性, 你应该考虑其他的尝试. C# 3提供了一个快捷方式: 如果你没有指定属性名称, 而仅仅使用表达式去对值进行评估, 那么编译器将会用表达式的最后一部分作为属性名. 这被称为发散性初始化器. 这意味着我们可以将上面的代码改写为:
&& 1: new { person.Name, IsAdult = (person.Age &= 18) }
将一个匿名对象初始化器变为一个发散性初始化器是很常见的&&通常当你想从一个对象拷贝一些属性到另外一个对象的时候发生, 而经常作为join操作的一部分. 一下显示了完整的代码, 使用了List.ConvertAll方法和匿名代理:
&& 1: List&Person& family = new List&Person&&& 2: {&& 3:&&&& new Person {Name=Holly, Age=31},&& 4:&&&& new Person {Name=Jon, Age=31},&& 5:&&&& new Person {Name=Tom, Age=4},&& 6:&&&& new Person {Name=Robin, Age=1},&& 7:&&&& new Person {Name=William, Age=1}&& 8: };&& 9: var converted = family.ConvertAll(delegate(Person person)& 10: { & 11:&&&& return new { person.Name, IsAdult = (person.Age &= 18) }; }& 12: );& 13: foreach (var person in converted)& 14: {& 15:&&&& Console.WriteLine({0} is an adult? {1},& 16:&&&& person.Name, person.IsAdult);& 17: }
上述的代码初始了使用了发散性初始化器, 我们还展示了匿名方法和代理类型推论的价值, 没有它们, 我们无法保持转换后的类型依然是强类型的. 因为我们无法指定TOutput参数在转换器当中的类型. 在完成转换之后, 我们可以使用一个迭代来遍历整个List并访问Name和IsAdult属性, 不过我们已经在使用另外一个类型了.
阅读(...) 评论()GSON使用笔记 -- 反序列化时GSON如何创建对象实例 - 推酷
GSON使用笔记 -- 反序列化时GSON如何创建对象实例
从一个问题开始
假设有这么一个类:
class MyObj {
public MyObj(int x) {
和下面的测试代码:
public void gson() {
MyObj obj = new Gson().fromJson(&{\&x\&:1}&, MyObj.class);
Assert.assertEquals(1, obj.x);
那么GSON是通过什么样的方式创建
对象的呢?答案可能会出乎你的意料(至少出乎了我的意料)。
InstanceCreator和ObjectConstructor
经过断点调试不难发现,GSON是使用
ObjectConstructor
来创建对象实例的,这点从代码注释里也能看的出来:
* Defines a generic object construction factory.
The purpose of this class
* is to construct a default instance of a class that can be used for object
* navigation while deserialization from its JSON representation.
* @author Inderjeet Singh
* @author Joel Leitch
public interface ObjectConstructor&T& {
* Returns a new instance.
public T construct();
那么ObjectConstructor从何而来呢?答案在
ConstructorConstructor
public &T& ObjectConstructor&T& get(TypeToken&T& typeToken) {
final Type type = typeToken.getType();
final Class&? super T& rawType = typeToken.getRawType();
// first try an instance creator
@SuppressWarnings(&unchecked&) // types must agree
final InstanceCreator&T& typeCreator = (InstanceCreator&T&) instanceCreators.get(type);
if (typeCreator != null) {
return new ObjectConstructor&T&() {
public T construct() {
return typeCreator.createInstance(type);
// Next try raw type match for instance creators
@SuppressWarnings(&unchecked&) // types must agree
final InstanceCreator&T& rawTypeCreator =
(InstanceCreator&T&) instanceCreators.get(rawType);
if (rawTypeCreator != null) {
return new ObjectConstructor&T&() {
public T construct() {
return rawTypeCreator.createInstance(type);
ObjectConstructor&T& defaultConstructor = newDefaultConstructor(rawType);
if (defaultConstructor != null) {
return defaultC
ObjectConstructor&T& defaultImplementation = newDefaultImplementationConstructor(type, rawType);
if (defaultImplementation != null) {
return defaultI
// finally try unsafe
return newUnsafeAllocator(type, rawType);
代码看起来很复杂,但实际上井然有序:
如果我们(通过GsonBuilder)注册过
InstanceCreator
,则交给InstanceCreator来创建实例
默认构造函数
,则通过反射调用默认构造函数创建实例
如果想要创建
等接口的实例,则走这里
否则交给神秘的
UnsafeAllocator
第一和第三种情况暂不考虑,下面来分析第二和第四种情况。
有默认构造函数的情况
按照前面的分析,这种情况GSON是通过调用默认构造函数来创建对象实例的,让我们证明这一点:
class MyObj {
public MyObj() {
throw new RuntimeException(&!!!&); // &---
@Test(expected = RuntimeException.class) // &---
public void gson() {
new Gson().fromJson(&{\&x\&:1}&, MyObj.class);
测试通过!
没有默认构造函数的情况
还是通过代码来证明这一点:
class MyObj {
public MyObj(int x) { // &---
throw new RuntimeException(&!!!&);
public void gson() {
MyObj obj = new Gson().fromJson(&{\&x\&:1}&, MyObj.class);
Assert.assertEquals(1, obj.x);
测试通过!
UnsafeAllocator
现在让我们一睹
UnsafeAllocator
* Do sneaky things to allocate objects without invoking their constructors.
* @author Joel Leitch
* @author Jesse Wilson
public abstract class UnsafeAllocator {
public abstract &T& T newInstance(Class&T& c) throws E
public static UnsafeAllocator create() {
// try JVM
// public class Unsafe {
public Object allocateInstance(Class&?& type);
Class&?& unsafeClass = Class.forName(&sun.misc.Unsafe&);
Field f = unsafeClass.getDeclaredField(&theUnsafe&);
f.setAccessible(true);
final Object unsafe = f.get(null);
final Method allocateInstance = unsafeClass.getMethod(&allocateInstance&, Class.class);
return new UnsafeAllocator() {
@SuppressWarnings(&unchecked&)
public &T& T newInstance(Class&T& c) throws Exception {
return (T) allocateInstance.invoke(unsafe, c);
} catch (Exception ignored) {
// give up
return new UnsafeAllocator() {
public &T& T newInstance(Class&T& c) {
throw new UnsupportedOperationException(&Cannot allocate & + c);
那么final字段是怎么处理的?
答案是,通过
。详细情况可以参考
,下面我们仅通过代码来证明这一点:
class MyObj {
public MyObj(int x) { // &---
public void setFinal() throws Exception {
MyObj obj = new MyObj(1);
Assert.assertEquals(1, obj.x);
Field f = obj.getClass().getField(&x&);
f.setAccessible(true); // &---
f.set(obj, 2);
Assert.assertEquals(2, obj.x);
测试通过!
反序列化时,如果一个类
没有默认构造函数
,那么GSON是通过
JDK内部API
来创建对象实例的,并且通过
字段赋值。
这种做法通常是很危险的,所以
非专业人士请勿效仿
已发表评论数()
已收藏到推刊!
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
没有分页内容
图片无法显示
视频无法显示
与原文不一致【数据】关于C#使用json,不能把匿名类对象转成json字符串吗?_科技_易房网
关于C#使用json,不能把匿名类对象转成json字符串吗?
作者:admin
使用的是DataContractJsonSerializer 在直接将linq查询出来的匿名类转json字符串的时候报错了 那么也就是说,我需要将某些数据转以成json字符串的时候,必须先定义一个模型类啥的来
使用的是DataContractJsonSerializer在直接将linq查询出来的匿名类转json字符串的时候报错了那么也就是说,我需要将某些数据转以成json字符串的时候,必须先定义一个模型类啥的来接纳数据?不能直接用匿名类吗?那这样的话,每个需要json字符串的场景我都要定义一个类?这样也太坑了吧……易房网小编为您精选了网友的解决办法,供您参考-----------------------------------------------------网友回答:
易房网小编为您精选了网友的解决办法,供您参考-----------------------------------------------------网友回答:
试试fastCSharp - Home
Console.WriteLine(new { A = 1, B = "C" }.ToJson());
易房网小编为您精选了网友的解决办法,供您参考-----------------------------------------------------网友回答:
Newtonsoft.Json
易房网小编为您精选了网友的解决办法,供您参考-----------------------------------------------------网友回答:
那个,你是怎么产生的任意类型都可以序列化的错觉的……
易房网小编为您精选了网友的解决办法,供您参考-----------------------------------------------------网友回答:
题主用的是
JsonDataContact 序列化器。这个序列化器是wcf 用的强类型规范attribute 方案
貌似不支持匿名类
@朴三世 说得对 这时候用 Newtonsoft.Json更舒服点
易房网小编为您精选了网友的解决办法,供您参考-----------------------------------------------------网友回答:
那个,匿名对象.ToString不就是JSON字符串了吗~楼主把你的代码粘上来,你放个模糊图片逗我呢
易房网小编为您精选了网友的解决办法,供您参考-----------------------------------------------------网友回答:
贴代码吧,我每天要转多少匿名类对象到json我都数不清楚还有,我看你这个不是转成json吧,我看着怎么那么像最原始的那种把对象序列化成字符串的方式啊~
1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将
追究责任;3.作者投稿可能会经我们编辑修改或补充。
澳洲警方首度披露成都美女留学生遇害细节
植物上刻名字拉着花照相 这些不文明行为你有吗?
社保费率今起阶段性降低 新条例护百姓“保命钱”
一天内中国三位领导人会见日本外相 分析:传递诚
南京栖霞山评选“最萌佛宝宝”[组图]
教师37载捐资助学 签协议捐赠眼角膜称希望帮助有
河南观光直升机坠入水库 2人生死不明(图)
警察车祸现场跪地10分钟 当"人肉垫子"安抚伤患
友情链接、商务合作QQ:创建一个学生类student,把该类的实例 对象序列化到文件_百度知道
创建一个学生类student,把该类的实例 对象序列化到文件
avaScriptSerializer
例如; }, CustomerName = &
string strJson = ScriptSerialize(cc).WriteLine(strJson);John&
Console:Student cc = new Student { Unid = 1
其他类似问题
为您推荐:
序列化的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁

我要回帖

更多关于 js创建匿名对象 的文章

 

随机推荐