微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Newtonsoft.Json部分操作系统不支持解决

Newtonsoft.Json.dll 在C#中可以帮助我们转换json数据,但是遗憾的少数操作系统不支持

例如winserver2002,Xp 2002 也许不完全是操作系统的问题,总之,部分系统下

是没有通过,具体原因不清楚


为了解决这一问题,我参考了http://www.cnblogs.com/tearer/archive/2012/04/01/2428869.html中介绍的两种方法中的第一个方法

这第一个方法中提到:”<属性名>k__backingField,经过测试,转换时会把对象属性加上的东西

为了解决这一问题,我又参考了http://blog.csdn.net/lion_6/article/details/11792951

就是做如下一种转换,[Serializable]不能丢,否则发现没有把数据转到对象中

[Serializable]
public class MyUser
{
/// <summary>
/// 用户昵称
/// </summary>
// [XmlElement("nick")]
// public string Nick { get; set; }

// /// <summary>
// /// 用户字符串ID
// /// </summary>
// [XmlElement("uid")]
// public string Uid { get; set; }
//
private string nick;
private string uid;
public string Nick
{
get { return nick; }
set { nick = value; }
}

public string Uid
{
get { return uid; }
set { uid = value; }
}
}

参考内容1:

C#的JSON数据格式转换方法

ASP.NET MVC中Json(value)方法转换成JsonResult格式的数据异步返回给JQuery进行处理,很爽,结果最近不用 ASP.NET MVC开发应用了,异步地区调用涉及到Json数据的获取发现居然没有好的Json格式数据转换方法像过去一样简单调用 很是不爽,搜了下找到个利用System.Runtime.Serialization.Json转换数据的方法,可以转换为JQuery可以识别的格式,不过 调用过程中发现它将实体类属性名称转换成:”<属性名>k__backingField ” 这种格式,调用起来很不方便,不过还是将这种方法编写的助手类贴出来: 注意需要引用: 首先,当然是项目是3.5的, 只引用一个System.Runtime.Serialization 是不够的, 还要添加 System.ServiceModel System.ServiceModel.Web 的引用,OK 代码如下:

/// <summary>
/// FileName: JSONHelper.cs
/// CLRVersion: 2.0.50727.3623
/// Author: Mikel
/// Corporation:
/// Description:JSON格式数据转换助手类
/// 1.将List<T>类型的数据转换为JSON格式
/// 2.将T类型对象转换为JSON格式对象
/// 3.将JSON格式对象转换为T类型对象
/// DateTime: 2011-09-13 14:11:34
/// </summary>
public static class JSONHelper
{
    /// <summary>
    /// 转换对象为JSON格式数据
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="obj">对象</param>
    /// <returns>字符格式的JSON数据</returns>
    public static string GetJSON<T>(object obj)
    {
        string result = String.Empty;
        try
        {
            System.Runtime.Serialization.Json.DataContractJsonSerializer serializer =
            new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(T));
            using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
            {
                serializer.WriteObject(ms,obj);
                result = System.Text.Encoding.UTF8.GetString(ms.ToArray());
            }
        }
        catch (Exception ex)
        {
            throw ex;
        }
        return result;
    }
    /// <summary>
    /// 转换List<T>的数据为JSON格式
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="vals">列表值</param>
    /// <returns>JSON格式数据</returns>
    public static string JSON<T>(List<T> vals)
    {
        System.Text.StringBuilder st = new System.Text.StringBuilder();
        try
        {
            System.Runtime.Serialization.Json.DataContractJsonSerializer s = new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(T));

            foreach (T city in vals)
            {
                using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
                {
                    s.WriteObject(ms,city);
                    st.Append(System.Text.Encoding.UTF8.GetString(ms.ToArray()));
                }
            }
        }
        catch (Exception ex)
        {
            throw ex;
        }

        return st.ToString();
    }
    /// <summary>
    /// JSON格式字符转换为T类型的对象
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="jsonStr"></param>
    /// <returns></returns>
    public static T ParseFormByJson<T>(string jsonStr)
    {
        T obj = Activator.CreateInstance<T>();
        using (System.IO.MemoryStream ms =
        new System.IO.MemoryStream(System.Text.Encoding.UTF8.GetBytes(jsonStr)))
        {
            System.Runtime.Serialization.Json.DataContractJsonSerializer serializer =
            new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(T));
            return (T)serializer.Readobject(ms);
        }
    }
}

还是觉得ASP.NET MVC的Json转换比较地道,于是翻找其源码,发现是利用的.net Framework 3.5特有的 c:\Program Files\Reference Assemblies\Microsoft\Framework\v3.5\System.Web.Extensions.dll 实现的Json数据格式转换,实现代码如下:

namespace System.Web.Mvc {
    using System;
    using System.Text;
    using System.Web;
    using System.Web.Script.Serialization;

    [AspNetHostingPermission(System.Security.Permissions.SecurityAction.LinkDemand,Level = AspNetHostingPermissionLevel.Minimal)]
    [AspNetHostingPermission(System.Security.Permissions.SecurityAction.InheritanceDemand,Level = AspNetHostingPermissionLevel.Minimal)]
    public class JsonResult : ActionResult {

        public Encoding ContentEncoding {
            get;
            set;
        }

        public string ContentType {
            get;
            set;
        }

        public object Data {
            get;
            set;
        }

        public override void ExecuteResult(ControllerContext context) {
            if (context == null) {
                throw new ArgumentNullException("context");
            }

            HttpResponseBase response = context.HttpContext.Response;

            if (!String.IsNullOrEmpty(ContentType)) {
                response.ContentType = ContentType;
            }
            else {
                response.ContentType = "application/json";
            }
            if (ContentEncoding != null) {
                response.ContentEncoding = ContentEncoding;
            }
            if (Data != null) {
#pragma warning disable 0618
                JavaScript.Serializer serializer = new JavaScript.Serializer();
                response.Write(serializer.Serialize(Data));
#pragma warning restore 0618
            }
        }
    }
}


看到这大家应该明白了,原来.net Framework3.5已经做好了转换的方法,只需要调用即可,不过提醒大家注意: 一定要先引用c:\Program Files\Reference Assemblies\Microsoft\Framework\v3.5\System.Web.Extensions.dll 才能使用JavaScriptSerializer serializer = new JavaScriptSerializer(); 切记!切记!

参考内容2:

C#对 Json的序列化和反序列化会出现“k_BackingField”

分类 net 282人阅读 评论(0) 收藏 举报

C#Json的序列化和反序列化会出现“k_BackingField

事情从Json的序列化和反序列化说起。

C#2.0的项目中,以前经常使用Json.Net实现序列化和反序列化。后来从c#3.0中开始使用新增的DataContractJsonSerializer进行json相关的操作。微软提供的原生类库使用上并不复杂,参考一下msdn你很容易就会写出序列化和反序列化的方法,比如经常被人使用的泛型方法如下:

对象转换成json

///<summary>

///对象转换成json

///</summary>

///<typeparamname="T"></typeparam>

///<paramname="jsonObject">需要格式化的对象</param>

///<returns>Json字符串</returns>

publicstaticstringDataContractJsonSerialize<T>(TjsonObject)

{

varserializer=newDataContractJsonSerializer(typeof(T));

stringjson=null;

using(varms=newMemoryStream())//定义一个stream用来存发序列化之后的内容

{

serializer.WriteObject(ms,jsonObject);

vardataBytes=newbyte[ms.Length];

ms.Position=0;

ms.Read(dataBytes,0,(int)ms.Length);

json=Encoding.UTF8.GetString(dataBytes);

ms.Close();

}

returnjson;

}

///<summary>

///json字符串转换成对象

///</summary>

///<typeparamname="T"></typeparam>

///<paramname="json">要转换成对象的json字符串</param>

///<returns></returns>

publicstaticTDataContractJsonDeserialize<T>(stringjson)

{

varserializer=newDataContractJsonSerializer(typeof(T));

varobj=default(T);

using(varms=newMemoryStream(Encoding.UTF8.GetBytes(json)))

{

obj=(T)serializer.Readobject(ms);

ms.Close();

}

returnobj;

}

不过使用该类库方法的过程中还是不慎意外发现了k_backingField

举例之前说一下我们的一个简单的实体类Person,它有如下定义:

Person实体

publicclassPerson

{

publicintId{get;set;}

publicstringFirstName{get;set;}

publicstringLastName{get;set;}

publicDateTimeBirthday{get;set;}

}

如果Person没有附加任何特性,经测试,可以成功使用上述泛型方法进行处理。

无特性Serialize

varperson=newPerson{Id=1,FirstName="jeff",LastName="wong",Birthday=newDateTime(1983,8,3)};

varjson=JsonHelper.DataContractJsonSerialize<Person>(person);

Console.WriteLine(json);

varresult=JsonHelper.DataContractJsonDeserialize<Person>(json);

if(result!=null)

{

Console.WriteLine("{0}{1}",result.FirstName,result.LastName);

}

而且json生成是正常的字符串:

{"Birthday":"\/Date(428688000000+0800)\/","FirstName":"jeff","Id":1,"LastName":"wong"}

可是当我们把Person实体上面设置Serializable特性后,莫名,我就很不解了:

{"<Birthday>k__backingField":"\/Date(428688000000+0800)\/","<FirstName>k__backingField":"jeff","<Id>k__backingField":1,"<LastName>k__backingField":"wong"}

搜索了一下,果然早就有人发现了类似的问题。后来上stackoverflow一查,查到好像和自动属性有点关系,大家可以看一下这一篇这一篇,而且评论比原帖精彩好像国内外大部分都是一致的。

有人说用Reflector反汇编可以看到自动属性生成的字段有前缀,可惜我一直使用ILSpy,兴致勃勃反编译查看了一下,没有没有是真的没有啊。

到这里你可能会想到,自动属性json会有k_backingField前缀,那传统那种属性的写法呢?

Serializable实体

[Serializable]

publicclassPerson

{

privateintid;

publicintId

{

get{returnid;}

set{id=value;}

}

privatestringfirstName;

publicstringFirstName

{

get{returnfirstName;}

set{firstName=value;}

}

privatestringlastName;

publicstringLastName

{

get{returnlastName;}

set{lastName=value;}

}

privateDateTimebirthday;

publicDateTimeBirthday

{

get{returnbirthday;}

set{birthday=value;}

}

}

OK,我们想一块去了,经测试,带Serializable特性的Person类,输出json一点问题没有:

{"birthday":"\/Date(428688000000+0800)\/","firstName":"jeff","id":1,"lastName":"wong"}

但是,请注意大小写(我挖了一个坑,上面的json是序列化属性吗?首字母有没有大写?)。

有没有兼容方式使自动属性输出json也正常呢?很简单,使用DataContractDataMember属性,哪一种写法输出json都没有问题的:

DataContract实体

[DataContract]

publicclassPerson

{

[DataMember]

publicintId{get;set;}

[DataMember]

publicstringFirstName{get;set;}

[DataMember]

publicstringLastName{get;set;}

[DataMember]

publicDateTimeBirthday{get;set;}

}

json输出带有k_backingField前缀的问题可能非常简单,这里只是善意地提醒,我个人曾经有过“惨痛”的教训,而且感觉还相当隐蔽,大家也要小心啊。

最后,在使用.netframework自带json有关类库的时候还碰到过特殊符号和时间格式转换的问题,网上有不少文章都讲到,相信不少人也有类似经历,这里就不说了。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐