1. 程式人生 > >JSON之Asp.net MVC C#對象轉JSON,DataTable轉JSON,List<T>轉JSON,JSON轉List<T>,JSON轉C#對象

JSON之Asp.net MVC C#對象轉JSON,DataTable轉JSON,List<T>轉JSON,JSON轉List<T>,JSON轉C#對象

技術分享 toolbar index 基本 枚舉 對象轉json tostring cab 拼接

一、JSON解析與字符串化

  JSON.stringify()  序列化對象、數組或原始值

  語法:JSON.stringify(o,filter,indent)  

    o,要轉換成JSON的對象、數組或原始值

    filter,指定要序列化的屬性名

    indent,格式化為可讀的代碼,可指定分隔符或指定的縮進空格個數

技術分享
        var man = { name: "張三", Age: 24, money: 123123 };
        var str1 = JSON.stringify(man); //基本序列化
        document.write(str1 + "<br/>"); //{"name":"張三","Age":24,"money":123123}
        var str2 = JSON.stringify(man, ["name", "Age"]);    //指定要序列化的屬性
        document.write(str2 + "<br/>"); //{"name":"張三","Age":24}
        var str3 = JSON.stringify(man,["name","Age","money"],"---");    //指定格式化數值
        document.write(str3);           //{ ---"name": "張三", ---"Age": 24, ---"money": 123123 }
技術分享

  JSON.parse()  反序列化一個字符串為JSON對象

  語法:JSON.parse(s)

     JSON.parse(s,reviver)  

     s,要解析的字符串。reviver,用來轉換解析值的可選函數

        var man = { name: "張三", Age: 17, money: 123123 };
        var str1 = JSON.stringify(man, ["name", "Age"]);    //指定要序列化的屬性
        var str2 = JSON.parse(str1);
        document.write(str2.name + str2.Age + str2.money);  //張三24undefined   由於money參數沒有序列化,所以undefined

另外由於JSON.parse存在兼容性問題,IE6,IE7並不支持此函數(目前,搜狗,360瀏覽器也不支持)。所以上網找了兩個兼容性比較好的字符串轉JSON方法,代碼如下:

技術分享
//第一種:eval方式解析
 function strToJson(str){  
      var json = eval(‘(‘ + str + ‘)‘);  
      return json;  
 } 
//第二種:new Function形式 
function strToJson(str){
    var json = (new Function("return " + str))();
    return json;
}
技術分享

  JSON是一種輕量級的數據交換格式,實質上就是一個javascript對象,因此格式與javascript定義的對象一樣。在數據傳輸過程中,JSON是以字符串的格式傳輸的。

   特別註意:如果obj本來就是一個JSON對象,那麽使用eval()函數轉換後(哪怕是多次轉換)還是JSON對象,但是使用parseJSON()函數處理後會有問題(拋出語法異常)。

  到目前為止學會了如果將一個javascript對象轉換為JSON,也知道了如何將JSON反轉換為javascript對象。現在來結合後臺程序,練下手。

  先來個jQuery獲取後臺返回的JSON數據並處理的例子,控制器代碼:

技術分享
        public ActionResult Index()
        {
            return View();
        }

        public JsonResult GetJSON()
        {
            return Json(new {Id=1,Name="劉備",Age=23},"text/html",JsonRequestBehavior.AllowGet);
        }
技術分享

  視圖代碼:

技術分享
    <title>JSON示例</title>
    <script src="/jquery-1.8.2.min.js" type="text/javascript"></script>
    <script type="text/javascript">
        $(function () {
            $("#btn1").click(function () {
                $.ajax({
                    url: "/Home/GetJSON",
                    type: "post",
                    dataType: "json",
                    success: function (response) {
                        $("#Id").text(response.Id);
                        $("#Name").text(response.Name);
                        $("#Age").text(response.Age);
                    }
                })
            })
        })
    </script>
</head>
<body>    
    <div id="imglist">
        <ul>
            <li id="Id"></li>
            <li id="Name"></li>
            <li id="Age"></li>
        </ul>
        <input type="button" id="btn1" value="確認" />
    </div>
</body>
</html>
技術分享

  此示例實現的效果是,當點擊按鈕時,三個li的值自動設置為需要的內容。

  細心的朋友應該註意到,在Result裏面返回了一個JsonRequestBehavior.AllowGet。其實這是一個枚舉,在MVC中的JSONResult裏面用於控制HTTP Get請求的處理方式,先來了解下這個枚舉。

  這是一個簡單枚舉,而且只有兩個選項,以兄弟我一貫的方式,依然用個列表展示出來。

成員           成員值        說明

AllowGet         0         允許來自客戶端的 HTTP GET 請求。

DenyGet          1        不允許來自客戶端的HTTP GET請求。

默認值為 DenyGet。允許 GET 請求可能會導致用戶在某一網站中仍處於已登錄狀態時訪問另一個網站。這可能會生成導致信息泄漏的安全漏洞。(當然這是微軟MSDN裏面的話)

  其實在本例中,這個選項完全可以刪開,完全沒影響。因為本例的AJAX請求使用的是post方式,但是如果將AJAX的請求設置為get時,如果再不設置該屬性為AllowGet時,那就真的獲取不到數據了。

  另外.net還提供了很好用的C#對象轉JSON的類,JavaScriptSerializer類,此類位於System.Web.Script.Serialization命名空間下。如要使用此命名空間,需要引用System.Web.Extensions庫文件。要想了解此類的詳細信息請查看。

  本處只給出一個簡單示例。先來看控制器代碼:

技術分享
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }

        public ActionResult GetJSON()
        {
            Person p = new Person();
            p.Id = 1;
            p.Name = "關羽";
            p.Age = 22;
            JavaScriptSerializer jss = new JavaScriptSerializer();
            string JsonStr = jss.Serialize(p);
            return Content(JsonStr);
        }

    }

    public class Person
    {
        public int Id
        {
            get;
            set;
        }

        public string Name
        {
            get;
            set;
        }

        public int Age
        {
            get;
            set;
        }
    }
技術分享

視圖代碼:

技術分享
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>JSON示例</title>
    <script src="/jquery-1.8.2.min.js" type="text/javascript"></script>
    <script type="text/javascript">
        $(function () {
            $("#btn1").click(function () {
                $.ajax({
                    url: "/Home/GetJSON",
                    type: "post",
                    dataType: "html",
                    success: function (response) {
                        var obj = JSON.parse(response);
                        $("#Id").text(obj.Id);
                        $("#Name").text(obj.Name);
                        $("#Age").text(obj.Age);
                    }
                })
            })
        })
    </script>
</head>
<body>    
    <div id="imglist">
        <ul>
            <li id="Id"></li>
            <li id="Name"></li>
            <li id="Age"></li>
        </ul>
        <input type="button" id="btn1" value="確認" />
    </div>
</body>
</html>
技術分享

  只代碼能夠將C#對象中的信息直接在javascript中處理並顯示。只是無論是返回JsonResult還是Content都需要JSON.parse()一下,不像第一個示例那樣不用轉換,不知道是測試出了問題,還是本類就只是這樣子。

  2013-4-26  今天終於正式了一個長久以來不註重的問題,就是jQuery AJAX返回的dataType:"json"的問題,因為只要設置了dataType為json,就無法進入到seccess。上網查了一下,統一的說法是,jQuery的json變得比較嚴格,會調用本機的json.Parse來轉換,如果存在什麽雙引號,單引號之類的不符合要求,則不會成功轉換,並且不會進入到success。這樣一來,.Net本身提供的序列化方法都不能用了。因此,建議還是使用dataType:text 然後再自己轉換。

C#對象轉Json

  要引用System.Runtime.Serialization.dll

  第一個例子:C#後臺將對象轉換為Json格式,然後由前臺解釋:

技術分享
public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }

        public ActionResult GetJson()
        {
            Person p = new Person(1, "關羽", 20);
            string str = ObjToJson2<Person>(p);
            //return Json(p,JsonRequestBehavior.AllowGet);  這種方法也行,而且是.Net提供的,有這個的時候,用這個比較好,沒有就自己搞的。
            return Content(str);
        }

        //單個對象轉Json 方法1
        public static string ObjToJson1<T>(T data)
        {
            JavaScriptSerializer jss = new JavaScriptSerializer();
            string JsonStr = jss.Serialize(data);
            return JsonStr;
        }

        //單個對象轉Json 方法2     //要特別註意,方法2要對類以及類的成員加上特性
        public static string ObjToJson2<T>(T obj)
        {
            try
            {
                System.Runtime.Serialization.Json.DataContractJsonSerializer serializer = new System.Runtime.Serialization.Json.DataContractJsonSerializer(obj.GetType());
                using (MemoryStream ms = new MemoryStream())
                {
                    serializer.WriteObject(ms, obj);
                    byte[] byteArr = ms.ToArray();
                    return Encoding.UTF8.GetString(byteArr);
                }
            }
            catch(Exception ex)
            {
                return null;
            }
        }
    }

    [DataContract]              //該類中的特性是對於System.Runtime.Serialization.Json.DataContractJsonSerializer即方法2的轉Json設置的,不設置不行。
    public class Person
    {
        public Person(int id, string name, int age)
        {
            Id = id;
            Name = name;
            Age = age;
        }
        [DataMember]            //對方法2要設置成員屬性
        public int Id
        {
            get;
            set;
        }
        [DataMember]
        public string Name
        {
            get;
            set;
        }
        [DataMember]
        public int Age
        {
            get;
            set;
        }
    }
技術分享

  /Home/Index視圖代碼:

技術分享
<html>
<head>
    <title>Json測試</title>
    <script src="/Scripts/jquery-1.7.2.min.js" type="text/javascript"></script>
    <script type="text/javascript">
        $(function () {
            $.ajax({
                url: "/Home/GetJson",
                dataType: "text",
                success: function (response) {
                    alert(response);
                    var obj = strToJson(response);
                    $("#div1").html("姓名:" + obj.Name + "  " + "年齡:" + obj.Age);
                    alert(obj.Name);
                }
            })
        })
        function strToJson(str) {
            var json = eval(‘(‘ + str + ‘)‘);
            return json;
        } 
    </script>
</head>
<body>
    <div id="div1">
        
    </div>
</body>
</html>
技術分享

  輸出結果如下:

  技術分享

Json字符串轉Model

  這裏實現的例子是,前臺用js拼接一段Json字符串,傳送上後臺,後臺再解釋為C#對象,並將年齡+1後返回該對象的Json。

   後臺代碼:

技術分享
namespace MvcApplication1.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {

            return View();
        }

        public ActionResult JsonToModel(string json)
        {
            Person p = ParseFromJson<Person>(json);
            p.Age = p.Age + 1;      //將年齡加大一歲,在序列化返回去

            return Json(p,JsonRequestBehavior.AllowGet);
        }

        /// <summary>
        /// 獲取Json的Model
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="szJson"></param>
        /// <returns></returns>
        public static T ParseFromJson<T>(string szJson)
        {
            T obj = Activator.CreateInstance<T>();  //註意 要有T類型要有無參構造函數
            using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(szJson)))
            {
                DataContractJsonSerializer serializer = new DataContractJsonSerializer(obj.GetType());
                return (T)serializer.ReadObject(ms);
            }
        }
    }

    [DataContract]              //該類中的特性是對於System.Runtime.Serialization.Json.DataContractJsonSerializer即方法2的轉Json設置的,不設置不行。
    public class Person
    {
        public Person()
        { }
        public Person(int id, string name, int age)
        {
            Id = id;
            Name = name;
            Age = age;
        }
        [DataMember]            //對方法2要設置成員屬性
        public int Id
        {
            get;
            set;
        }
        [DataMember]
        public string Name
        {
            get;
            set;
        }
        [DataMember]
        public int Age
        {
            get;
            set;
        }
    }
}
技術分享

  前臺代碼:

技術分享
<html>
<head>
    <title>Json測試</title>
    <script src="/Scripts/jquery-1.7.2.min.js" type="text/javascript"></script>
    <script type="text/javascript">
        $(function () {
            var o = { Id: 1, Name: "劉備", Age: 23 };
            $.ajax({
                url: "/Home/JsonToModel",
                dataType: "text",
                type:"post",
                data:{
                    json: JSON.stringify(o)    //將o序列化為字符串
                },
                success: function (response) {
                    alert(response);
                    var obj = strToJson(response);
                    $("#div1").html("姓名:" + obj.Name + "  " + "年齡:" + obj.Age);
                    alert(obj.Name);
                }
            })
        })
        function strToJson(str) {
            var json = eval(‘(‘ + str + ‘)‘);
            return json;
        } 
    </script>
</head>
<body>
    <div id="div1">
    </div>
</body>
</html>
技術分享

  註意到我們前臺拼接的年齡是23。但是返回的是24,說明已經拼接成功了。

  技術分享

DataTable轉JSON

  這裏例子是在DataTable轉換為JSON的方法,其中還包括了前臺javascript解釋:

技術分享
    public class HomeController : Controller
    {
        public ActionResult Index()
        {

            return View();
        }

        public ActionResult GetJson()
        {
            DataTable dt = new DataTable();
            dt.Columns.Add("Id");
            dt.Columns.Add("Name");
            dt.Columns.Add("Age");
            dt.Rows.Add("1", "關羽", "22");
            dt.Rows.Add("2", "趙雲", "23");
            dt.Rows.Add("3", "張飛", "21");
            //string strJson = DataTableToJson1(dt);
            string strJson = dt.ToJson();
            //return Json(dt, JsonRequestBehavior.AllowGet);      //貌似這個是不支持的,不支持直接將DataTable轉換為Json
            return Content(strJson);
        }

         ///<summary>
         ///方法1    這個方法其實就是DataTable拼接成字符串而已,沒什麽出奇的
         ///</summary>
         ///<param name="dt"></param>
         ///<returns></returns>
        public static string DataTableToJson1(DataTable dt)
        {
            if (dt.Rows.Count == 0)
            {
                return "";
            }

            StringBuilder jsonBuilder = new StringBuilder();
            jsonBuilder.Append("[");
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                jsonBuilder.Append("{");
                for (int j = 0; j < dt.Columns.Count; j++)
                {
                    jsonBuilder.Append("\"");
                    jsonBuilder.Append(dt.Columns[j].ColumnName);
                    jsonBuilder.Append("\":\"");
                    jsonBuilder.Append(dt.Rows[i][j].ToString());
                    jsonBuilder.Append("\",");
                }
                jsonBuilder.Remove(jsonBuilder.Length - 1, 1);
                jsonBuilder.Append("},");
            }
            jsonBuilder.Remove(jsonBuilder.Length - 1, 1);
            jsonBuilder.Append("]");
            return jsonBuilder.ToString();
        }

    }

    /// <summary>
    /// 寫成DataTable的擴展方法是這樣
    /// </summary>
    public static class JsonTableHelper
    {
        /// <summary> 
        /// 返回對象序列化 
        /// </summary> 
        /// <param name="obj">源對象</param> 
        /// <returns>json數據</returns> 
        public static string ToJson(object obj)
        {
            JavaScriptSerializer serialize = new JavaScriptSerializer();
            return serialize.Serialize(obj);
        }

        /// <summary> 
        /// 控制深度 
        /// </summary> 
        /// <param name="obj">源對象</param> 
        /// <param name="recursionDepth">深度</param> 
        /// <returns>json數據</returns> 
        public static string ToJson(object obj, int recursionDepth)
        {
            JavaScriptSerializer serialize = new JavaScriptSerializer();
            serialize.RecursionLimit = recursionDepth;
            return serialize.Serialize(obj);
        }

        /// <summary> 
        /// DataTable轉為json 
        /// </summary> 
        /// <param name="dt">DataTable</param> 
        /// <returns>json數據</returns> 
        public static string ToJson(this DataTable dt)
        {
            List<object> dic = new List<object>();

            foreach (DataRow dr in dt.Rows)
            {
                Dictionary<string, object> result = new Dictionary<string, object>();

                foreach (DataColumn dc in dt.Columns)
                {
                    result.Add(dc.ColumnName, dr[dc].ToString());
                }
                dic.Add(result);
            }
            return ToJson(dic);
        }
    }
技術分享

  其中/Home/Index的視圖代碼為:

技術分享
<html>
<head>
    <title>Json測試</title>
    <script src="/Scripts/jquery-1.7.2.min.js" type="text/javascript"></script>
    <script type="text/javascript">
        $(function () {
            $.ajax({
                url: "/Home/GetJson",
                dataType: "text",
                success: function (response) {
                    alert(response);
                    var obj = strToJson(response);
                    var str = "";
                    for (var i = 0; i < obj.length; i++) {
                        str += "姓名:" + obj[i].Name + "  " + "年齡:" + obj[i].Age;
                    }
                    $("#div1").html(str);
                }
            })
        })
        function strToJson(str) {
            var json = eval(‘(‘ + str + ‘)‘);
            return json;
        } 
    </script>
</head>
<body>
    <div id="div1">
    </div>
</body>
</html>
技術分享

  輸出結果如下:

  技術分享

List<T>轉Json

  List<T>轉Json從方法上來說,與普通對象轉Json代碼是一樣的,因此這也是為什麽微軟的JsonResult能夠正確返回Json字符串的原因了。

  後臺代碼:

技術分享
public class HomeController : Controller
    {
        public ActionResult Index()
        {

            return View();
        }

        public ActionResult GetJson()
        {
            List<Person> list = new List<Person>();
            list.Add(new Person(1, "張飛", 21));
            list.Add(new Person(2, "關羽", 22));
            list.Add(new Person(3, "劉備", 23));
            //return Json(list,JsonRequestBehavior.AllowGet);     //.Net還是很威武的,這行代碼是可以運行並得到正確結果的,然後註釋來看看前輩們的List<T>轉Json的代碼//
            string strJson = ObjToJson<List<Person>>(list);       //泛泛型?    這代碼怎麽感覺怪怪的。
            return Content(strJson);
        }

        [NonAction]
        public static string ObjToJson<T>(T data)
        {
            try
            {
                System.Runtime.Serialization.Json.DataContractJsonSerializer serializer = new System.Runtime.Serialization.Json.DataContractJsonSerializer(data.GetType());
                using (MemoryStream ms = new MemoryStream())
                {
                    serializer.WriteObject(ms, data);
                    return Encoding.UTF8.GetString(ms.ToArray());
                }
            }
            catch
            {
                return null;
            }
        }
    }

    [DataContract]              //該類中的特性是對於System.Runtime.Serialization.Json.DataContractJsonSerializer即方法2的轉Json設置的,不設置不行。
    public class Person
    {
        public Person()
        { }
        public Person(int id, string name, int age)
        {
            Id = id;
            Name = name;
            Age = age;
        }
        [DataMember]            //對方法2要設置成員屬性
        public int Id
        {
            get;
            set;
        }
        [DataMember]
        public string Name
        {
            get;
            set;
        }
        [DataMember]
        public int Age
        {
            get;
            set;
        }
    }
技術分享

  /Home/Index視圖代碼,這個與DataTable是一樣的,反正都是轉成數組的Json字符串。

技術分享
<html>
<head>
    <title>Json測試</title>
    <script src="/Scripts/jquery-1.7.2.min.js" type="text/javascript"></script>
    <script type="text/javascript">
        $(function () {
            $.ajax({
                url: "/Home/GetJson",
                dataType: "text",
                success: function (response) {
                    alert(response);
                    var obj = strToJson(response);
                    var str = "";
                    for (var i = 0; i < obj.length; i++) {
                        str += "姓名:" + obj[i].Name + "  " + "年齡:" + obj[i].Age;
                    }
                    $("#div1").html(str);
                }
            })
        })
        function strToJson(str) {
            var json = eval(‘(‘ + str + ‘)‘);
            return json;
        } 
    </script>
</head>
<body>
    <div id="div1">
    </div>
</body>
</html>
技術分享

  技術分享

JSON轉List<T>

  本次的例子是先在本地拼接一個Json對象,然後發送到後臺轉成List<T>對象,再循環,年齡+10再返回Json

  後臺代碼:

技術分享
public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }

        public ActionResult GetJson(string json)
        {
            List<Person> list = JsonToObj(json, typeof(List<Person>)) as List<Person>;     //貌似List<T> 與 普通類型是一樣的 註意得到list的數量

            //循環將年齡+10後再返回Json
            for (int i = 0; i < list.Count; i++)
            {
                list[i].Age = list[i].Age + 10;
            }
            return Json(list,JsonRequestBehavior.AllowGet);     //.Net還是很威武的,這行代碼是可以運行並得到正確結果的,然後註釋來看看前輩們的List<T>轉Json的代碼
        }

        public static Object JsonToObj(String json, Type t)
        {
            try
            {
                System.Runtime.Serialization.Json.DataContractJsonSerializer serializer = new System.Runtime.Serialization.Json.DataContractJsonSerializer(t);
                using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(json)))
                {
                    return serializer.ReadObject(ms);
                }
            }
            catch
            {
                return null;
            }
        }
    }

    [DataContract]              //該類中的特性是對於System.Runtime.Serialization.Json.DataContractJsonSerializer即方法2的轉Json設置的,不設置不行。
    public class Person
    {
        public Person()
        { }
        public Person(int id, string name, int age)
        {
            Id = id;
            Name = name;
            Age = age;
        }
        [DataMember]            //對方法2要設置成員屬性
        public int Id
        {
            get;
            set;
        }
        [DataMember]
        public string Name
        {
            get;
            set;
        }
        [DataMember]
        public int Age
        {
            get;
            set;
        }
    }
技術分享

  前臺Html代碼:

技術分享
<html>
<head>
    <title>Json測試</title>
    <script src="/Scripts/jquery-1.7.2.min.js" type="text/javascript"></script>
    <script type="text/javascript">
        $(function () {
            var o1 = { Id: 1, Name: "張三", Age: 21 };
            var o2 = { Id: 2, Name: "李四", Age: 22 };
            var o3 = { Id: 3, Name: "王五", Age: 23 };
            var arr = [o1, o2, o3];
            var str = JSON.stringify(arr);
            $.ajax({
                url: "/Home/GetJson",
                dataType: "text",
                data: {
                    json:str
                },
                type:"post",
                success: function (response) {
                    alert(response);
                    var obj = strToJson(response);
                    var str = "";
                    for (var i = 0; i < obj.length; i++) {
                        str += "姓名:" + obj[i].Name + "  " + "年齡:" + obj[i].Age;
                    }
                    $("#div1").html(str);
                }
            })
        })
        function strToJson(str) {
            var json = eval(‘(‘ + str + ‘)‘);
            return json;
        } 
    </script>
</head>
<body>
    <div id="div1">
    </div>
</body>
</html>
技術分享

  輸出結果如圖所示:

  技術分享

  留意到年齡已經全部加10了。

  下面再給出一個不錯的方法:

  JavaScriptSerializer sr = new JavaScriptSerializer();
  JQGrilBind jqgb = sr.Deserialize(filters, typeof(JQGrilBind)) as JQGrilBind;  //filters為json字符串

MVC return Json()註意事項

  對於MVC中return Json()這個默認的輔助方法。

  1、如果傳入的是對象,那麽轉Json出來的對象就是javascript對象。

  2、如果傳入的是List<Model>、Array這種類型的數據,那麽轉Json出來的是javascript數組。

  因此,要註意下,比如對於jQueryEasyUI的Tree來說,如果它接受的是javascript數組,那麽就要返回對應的格式。

JSON之Asp.net MVC C#對象轉JSON,DataTable轉JSON,List<T>轉JSON,JSON轉List<T>,JSON轉C#對象