首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >JavaScriptSerializer.Deserialize -如何更改字段名

JavaScriptSerializer.Deserialize -如何更改字段名
EN

Stack Overflow用户
提问于 2009-07-08 11:49:39
回答 8查看 103.3K关注 0票数 74

汇总:如何在使用JavaScriptSerializer.Deserialize时将JSON数据中的字段名映射到.Net对象的字段名?

更长版本的:下面的JSON数据来自服务器API (不是用.Net编写的)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{"user_id":1234, "detail_level":"low"}

我有以下C#对象:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[Serializable]
public class DataObject
{
    [XmlElement("user_id")]
    public int UserId { get; set; }

    [XmlElement("detail_level")]
    public DetailLevel DetailLevel { get; set; }
}

其中,DetailLevel是一个枚举,其中"Low“作为值之一。

此测试失败:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[TestMethod]
public void DataObjectSimpleParseTest()
{
    JavaScriptSerializer serializer = new JavaScriptSerializer();
    DataObject dataObject = serializer.Deserialize<DataObject>(JsonData);

    Assert.IsNotNull(dataObject);
    Assert.AreEqual(DetailLevel.Low, dataObject.DetailLevel);
    Assert.AreEqual(1234, dataObject.UserId);
}

最后两个断言失败,因为在这些字段中没有数据。如果我将JSON数据更改为

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 {"userid":1234, "detaillevel":"low"}

然后它就过去了。但是我不能改变服务器的行为,我希望客户端类在C#成语中具有名称良好的属性。我不能使用LINQ,因为我希望它在Silverlight之外工作。看起来XmlElement标签没有任何效果。我不知道我是从哪里得到他们的相关概念的,他们可能不是。

如何在JavaScriptSerializer中进行字段名映射?完全可以做到吗?

EN

回答 8

Stack Overflow用户

发布于 2009-07-10 05:43:07

我又试了一次,使用DataContractJsonSerializer类。这解决了这个问题:

代码如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
using System.Runtime.Serialization;

[DataContract]
public class DataObject
{
    [DataMember(Name = "user_id")]
    public int UserId { get; set; }

    [DataMember(Name = "detail_level")]
    public string DetailLevel { get; set; }
}

而测试是:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
using System.Runtime.Serialization.Json;

[TestMethod]
public void DataObjectSimpleParseTest()
{
        DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(DataObject));

        MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(JsonData));
        DataObject dataObject = serializer.ReadObject(ms) as DataObject;

        Assert.IsNotNull(dataObject);
        Assert.AreEqual("low", dataObject.DetailLevel);
        Assert.AreEqual(1234, dataObject.UserId);
}

唯一的缺点是,我必须将DetailLevel从枚举更改为字符串--如果您保持枚举类型不变,则DataContractJsonSerializer希望读取一个数值,但失败。有关更多细节,请参见DataContractJsonSerializer和Enum

在我看来,这是相当糟糕的,特别是在JavaScriptSerializer正确处理它的情况下。这是尝试将字符串解析为枚举的例外情况:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
System.Runtime.Serialization.SerializationException: There was an error deserializing the object of type DataObject. The value 'low' cannot be parsed as the type 'Int64'. --->
System.Xml.XmlException: The value 'low' cannot be parsed as the type 'Int64'. --->  
System.FormatException: Input string was not in a correct format

这样的标记并不能改变这种行为:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[DataContract]
public enum DetailLevel
{
    [EnumMember(Value = "low")]
    Low,
   ...
 }

这似乎也适用于Silverlight。

票数 73
EN

Stack Overflow用户

发布于 2010-01-04 20:49:16

通过创建自定义JavaScriptConverter,您可以将任何名称映射到任何属性。但它确实需要手工编码的地图,这不是理想的。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class DataObjectJavaScriptConverter : JavaScriptConverter
{
    private static readonly Type[] _supportedTypes = new[]
    {
        typeof( DataObject )
    };

    public override IEnumerable<Type> SupportedTypes 
    { 
        get { return _supportedTypes; } 
    }

    public override object Deserialize( IDictionary<string, object> dictionary, 
                                        Type type, 
                                        JavaScriptSerializer serializer )
    {
        if( type == typeof( DataObject ) )
        {
            var obj = new DataObject();
            if( dictionary.ContainsKey( "user_id" ) )
                obj.UserId = serializer.ConvertToType<int>( 
                                           dictionary["user_id"] );
            if( dictionary.ContainsKey( "detail_level" ) )
                obj.DetailLevel = serializer.ConvertToType<DetailLevel>(
                                           dictionary["detail_level"] );

            return obj;
        }

        return null;
    }

    public override IDictionary<string, object> Serialize( 
            object obj, 
            JavaScriptSerializer serializer )
    {
        var dataObj = obj as DataObject;
        if( dataObj != null )
        {
            return new Dictionary<string,object>
            {
                {"user_id", dataObj.UserId },
                {"detail_level", dataObj.DetailLevel }
            }
        }
        return new Dictionary<string, object>();
    }
}

然后,您可以像这样反序列化:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var serializer = new JavaScriptSerializer();
serialzer.RegisterConverters( new[]{ new DataObjectJavaScriptConverter() } );
var dataObj = serializer.Deserialize<DataObject>( json );
票数 20
EN

Stack Overflow用户

发布于 2009-07-10 18:24:41

Json.NET会做你想做的事情(免责声明:我是软件包的作者)。它支持读取DataContract/DataMember属性以及它自己的属性来更改属性名。还有一个StringEnumConverter类,用于将枚举值序列化为名称而不是数字。

票数 13
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1100191

复制
相关文章
如何更改SELinux模式
Security Enhanced Linux是一个Linux安全模块,用于强制或基于角色的访问控制。SELinux默认与CentOS和Fedora打包在一起,可以以三种模式之一运行:禁用、允许或强制执行。
温浪
2018/08/20
4.3K0
mysql(mariadb)如何更改root密码
mysql(或者mariadb,她是mysql的一个分支,完全开源,新版本的linux系统默认安装的是mariadb)如何更改root密码呢?我们主要介绍命令mysqladmin来实现。
周小董
2019/03/25
6.5K0
mysql(mariadb)如何更改root密码
mysql字段名
字段属性:null/not null,primary key,auto_increment,unique key,comment,default
十月梦想
2018/08/29
5.4K0
如何更改滚动条样式?
如何自定义浏览器的滚动条呢,下面给大家讲解一下,其实很简单,通过设定css样式就可以实现。
申霖
2019/12/27
2.5K0
如何更改滚动条样式?
oracle中更改表名语句,转:取Oracle 表名 字段名 注释等实用语句
select t.*,i.index_type fromuser_ind_columns t,user_indexes i
全栈程序员站长
2022/08/29
1.3K0
如何更改伪元素的样式
在前端开发中我们会经常用到伪元素,有时候需要通过js来修改伪元素的样式,那么有哪几种方式来修改伪元素的样式呢?
挥刀北上
2021/01/27
9.3K0
如何更改伪元素的样式
vscode如何更改文件默认保存路径
一 二 三
ydymz
2021/01/05
11.6K0
vscode如何更改文件默认保存路径
如何使用Symlink更改MySQL数据目录
数据库随着时间的推移而增长,有时会超出文件系统的空间。当它们与操作系统的其余部分位于同一分区时,可能会遇到I/O冲突。RAID,网络块存储和其他设备可以提供冗余和其他所需的功能。无论您是要添加更多空间,评估优化性能的方法,还是希望利用其他存储功能,本教程都将指导您重新定位MySQL的数据目录。
心语花束
2018/07/26
3.6K0
如何更改 Linux 的 I/O 调度器
Linux 的 I/O 调度器是一个以块式 I/O 访问存储卷的进程,有时也叫磁盘调度器。Linux I/O 调度器的工作机制是控制块设备的请求队列:确定队列中哪些 I/O 的优先级更高以及何时下发 I/O 到块设备,以此来减少磁盘寻道时间,从而提高系统的吞吐量。
Debian中国
2018/12/20
4.5K0
centos7如何更改ip地址
这里最好是使用root用户,然后使用ls命令找到网络的配置文件。 我这里的配置文件是ifcfg-ens33. 然后使用vi命令进入文件进行编辑网络的ip地址等信息。 然后按键盘i进入编辑模式,更改ip地址等信息。
全栈程序员站长
2022/07/23
7.7K0
centos7如何更改ip地址
如何更改 Linux 文件和目录权限?
在Linux系统中,文件和目录权限是安全性和访问控制的关键组成部分。正确设置文件和目录的权限可以确保只有授权的用户能够读取、写入或执行这些文件和目录。
网络技术联盟站
2023/05/29
5.3K0
如何更改 Linux 文件和目录权限?
如何在Linux中更改SSH端口?
SSH(Secure Shell)是一种安全的远程登录协议,它允许您通过网络远程连接到Linux系统并进行管理操作。默认情况下,SSH使用22端口进行通信。然而,为了增强系统的安全性,有时候我们需要更改SSH端口,以减少潜在的攻击。
网络技术联盟站
2023/05/25
9.4K0
如何在Linux中更改SSH端口?
Simulink如何设置更改ode仿真算法?
1、点击[Simulink] 2、点击[Create Model] 3、点击[Model Configuration Parameters] 4、点击[auto] 5、点击[ode45] 6、点击[Solver Details]
裴来凡
2022/05/28
3.1K0
Simulink如何设置更改ode仿真算法?
Linux下如何in-place更改文件
前几天下班在地铁上,听到身边有两个小伙子在讨论,如何in-place的修改一个文件,路上想了半天没有好的办法。等到了家里一番探究,终于找到可行的方案了。
netkiddy
2020/03/15
2.8K0
如何更改github工程的语言属性
当创建github项目的时候,github本身会根据提交文件的数量来自动推断工程的开发语言,有时这种推断结果会与实际情况不太相符。
Python疯子
2018/09/06
3.4K0
如何在 Git 上更改分支名称?
在 Git 版本控制系统中,分支是非常重要的概念。分支允许你在项目中进行并行开发和实验,同时保持主分支的稳定性。有时候,你可能需要更改已存在的分支名称,例如纠正拼写错误或者为了更好地描述分支的内容。本文将详细介绍如何在 Git 上更改分支名称。
网络技术联盟站
2023/06/19
1.9K0
如何在 Git 上更改分支名称?
如何更改 Ubuntu 的终端的颜色
但是,如果你想要一个独一无二的的终端体验或者符合你自身品位的一些东西,你也可以改变你的 Ubuntu 的终端的颜色。
用户1880875
2021/11/08
14.5K0
点击加载更多

相似问题

如何重写JavaScriptSerializer.Deserialize<T>()

12

JavaScriptSerializer.Deserialize数组

268

使用JavaScriptSerializer.Deserialize

13

将JavaScriptSerializer.Deserialize()放入字典

36

如何更改ElasticSearch字段名

10
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文