在MVC中使用Json.Net序列化和反序列化Json对象

在.Net的MVC开发中,经常会使用到Json对象,于是,系统提供了JsonResult这个对象,其本质是调用.Net系统自带的Json序列化类JavaScriptSerializer对数据对象进行序列化。但是这个系统自带的Json序列化对象方法没有Json.Net好用,于是打算有些时候用Json.Net替代默认的实现。

要实现有时候用Json.Net,有时候用默认实现,那么就要保证系统中两种实现并存。对于Server将对象序列化成Json传给Client很简单,我们只需要建立一个新的ActionResult,我们命名为JsonNetResult,然后在Get时,return这个JsonNetResult即可。JsonNetResult的代码实现为:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MvcJsonNet
{
 using System.IO;
 using System.Web;
 using System.Web.Mvc;
 using Newtonsoft.Json;

 public class JsonNetResult : JsonResult
 {
 public JsonNetResult()
 {
 Settings = new JsonSerializerSettings
 {
 ReferenceLoopHandling = ReferenceLoopHandling.Error
 };
 }
 public JsonNetResult(object data, JsonRequestBehavior behavior = JsonRequestBehavior.AllowGet, string contentType=null, Encoding contentEncoding=null)
 {
 this.Data = data;
 this.JsonRequestBehavior = behavior;
 this.ContentEncoding = contentEncoding;
 this.ContentType = contentType;
 }

 public JsonSerializerSettings Settings { get; private set; }

 public override void ExecuteResult(ControllerContext context)
 {

 if (context == null)
 throw new ArgumentNullException("context");
 if (this.JsonRequestBehavior == JsonRequestBehavior.DenyGet && string.Equals(context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
 throw new InvalidOperationException("JSON GET is not allowed");

 HttpResponseBase response = context.HttpContext.Response;
 response.ContentType = string.IsNullOrEmpty(this.ContentType) ? "application/json" : this.ContentType;

 if (this.ContentEncoding != null)
 response.ContentEncoding = this.ContentEncoding;
 if (this.Data == null)
 return;

 var scriptSerializer = JsonSerializer.Create(this.Settings);

 using (var sw = new StringWriter())
 {
 scriptSerializer.Serialize(sw, this.Data);
 response.Write(sw.ToString());
 }
 }
 }
}

要返回一个Json.Net序号列后的对象,那么调用方法是:

[HttpGet]
public ActionResult GetJsonNet()
{
 var myClass = InitClass();
 return new JsonNetResult(myClass);
}

这是Get方法,但是对于ClientPost一个Json回Server,那么就比较麻烦了,需要修改好几处地方:

1,建立Json.Net的ValueProviderFactory,这个类主要就是用于Json字符串的反序列化。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace MvcJsonNet
{
 using System.Collections;
 using System.Dynamic;
 using System.Globalization;
 using System.IO;
 using System.Web.Mvc;
 using System.Web.Script.Serialization;
 using Newtonsoft.Json;

 public class JsonNetValueProviderFactory : ValueProviderFactory
 {
 private void AddToBackingStore(Dictionary<string, object> backingStore, string prefix, object value)
 {
 IDictionary<string, object> d = value as IDictionary<string, object>;
 if (d != null)
 {
 foreach (KeyValuePair<string, object> entry in d)
 {
 AddToBackingStore(backingStore, MakePropertyKey(prefix, entry.Key), entry.Value);
 }
 return;
 }

 IList l = value as IList;
 if (l != null)
 {
 for (int i = 0; i < l.Count; i++)
 {
 AddToBackingStore(backingStore, MakeArrayKey(prefix, i), l[i]);
 }
 return;
 }

 // primitive
 backingStore[prefix] = value;
 }

 private object GetDeserializedObject(ControllerContext controllerContext)
 {
 if (!controllerContext.HttpContext.Request.ContentType.StartsWith("application/json", StringComparison.InvariantCultureIgnoreCase))
 {
 // not JSON request return null;
 }

 StreamReader reader = new StreamReader(controllerContext.HttpContext.Request.InputStream);
 string bodyText = reader.ReadToEnd();
 if (String.IsNullOrEmpty(bodyText))
 {
 // no JSON data return null;
 }
 //接下来的代码是关键,判断content type,如果是json.net,那么就使用Json.Net的反序列化方法,如果不是,那么就使用系统默认的反序列化方法 if (controllerContext.HttpContext.Request.ContentType.StartsWith("application/json.net", StringComparison.InvariantCultureIgnoreCase))
 {
 var jsonData = JsonConvert.DeserializeObject<ExpandoObject>(bodyText);
 return jsonData;
 }
 else
 {
 JavaScriptSerializer serializer = new JavaScriptSerializer();
 object jsonData = serializer.DeserializeObject(bodyText);
 return jsonData;
 }
 }

 public override IValueProvider GetValueProvider(ControllerContext controllerContext)
 {
 if (controllerContext == null)
 {
 throw new ArgumentNullException("controllerContext");
 }

 object jsonData = GetDeserializedObject(controllerContext);
 if (jsonData == null)
 {
 return null;
 }

 Dictionary<string, object> backingStore = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
 AddToBackingStore(backingStore, String.Empty, jsonData);
 return new DictionaryValueProvider<object>(backingStore, CultureInfo.CurrentCulture);
 }

 private string MakeArrayKey(string prefix, int index)
 {
 return prefix + "[" + index.ToString(CultureInfo.InvariantCulture) + "]";
 }

 private string MakePropertyKey(string prefix, string propertyName)
 {
 return (String.IsNullOrEmpty(prefix)) ? propertyName : prefix + "." + propertyName;
 }
 }
}

2,在初始化MVC时替换掉默认的JsonValueProviderFactory。
在Global.asax的Application_Start时,写入以下代码:

ValueProviderFactories.Factories.Remove(ValueProviderFactories.Factories.OfType<JsonValueProviderFactory>().FirstOrDefault());
ValueProviderFactories.Factories.Add(new JsonNetValueProviderFactory());

3,建立新的ModelBinder,命名为JsonNetModelBinder。

namespace MvcJsonNet
{
 using System;
 using System.ComponentModel;
 using System.Diagnostics;
 using System.Globalization;
 using System.Linq;
 using System.Web.Mvc;
 using Newtonsoft.Json;

 public class JsonNetModelBinder : DefaultModelBinder
 {
 protected override void BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext,
 PropertyDescriptor propertyDescriptor)
 {
 Debug.WriteLine("BindProperty");
 if (!controllerContext.HttpContext.Request.ContentType.StartsWith("application/json.net",
 StringComparison
 .InvariantCultureIgnoreCase))
 {
 //根据Content type来判断,只有json.net这种content type的才会使用该ModelBinder,否则使用默认的Binder base.BindProperty(controllerContext, bindingContext, propertyDescriptor);
 return;
 }

 // need to skip properties that aren't part of the request, else we might hit a StackOverflowException string name = propertyDescriptor.Name;
 foreach (object attribute in propertyDescriptor.Attributes)
 {
 if (attribute is JsonPropertyAttribute)
 {
 var jp = attribute as JsonPropertyAttribute;
 name = jp.PropertyName;
 }
 }

 string fullPropertyKey = CreateSubPropertyName(bindingContext.ModelName, name);
 if (!bindingContext.ValueProvider.ContainsPrefix(fullPropertyKey))
 {
 return;
 }

 // call into the property's model binder
 IModelBinder propertyBinder = Binders.GetBinder(propertyDescriptor.PropertyType);
 object originalPropertyValue = propertyDescriptor.GetValue(bindingContext.Model);
 ModelMetadata propertyMetadata = bindingContext.PropertyMetadata[propertyDescriptor.Name];
 propertyMetadata.Model = originalPropertyValue;
 var innerBindingContext = new ModelBindingContext
 {
 ModelMetadata = propertyMetadata,
 ModelName = fullPropertyKey,
 ModelState = bindingContext.ModelState,
 ValueProvider = bindingContext.ValueProvider
 };
 object newPropertyValue = GetPropertyValue(controllerContext, innerBindingContext, propertyDescriptor,
 propertyBinder);
 propertyMetadata.Model = newPropertyValue;

 // validation
 ModelState modelState = bindingContext.ModelState[fullPropertyKey];
 if (modelState == null || modelState.Errors.Count == 0)
 {
 if (OnPropertyValidating(controllerContext, bindingContext, propertyDescriptor, newPropertyValue))
 {
 SetProperty(controllerContext, bindingContext, propertyDescriptor, newPropertyValue);
 OnPropertyValidated(controllerContext, bindingContext, propertyDescriptor, newPropertyValue);
 }
 }
 else
 {
 SetProperty(controllerContext, bindingContext, propertyDescriptor, newPropertyValue);

 // Convert FormatExceptions (type conversion failures) into InvalidValue messages foreach (
 ModelError error in
 modelState.Errors.Where(err => String.IsNullOrEmpty(err.ErrorMessage) && err.Exception != null)
 .ToList())
 {
 for (Exception exception = error.Exception; exception != null; exception = exception.InnerException)
 {
 if (exception is FormatException)
 {
 string displayName = propertyMetadata.GetDisplayName();
 string errorMessageTemplate = "The value '{0}' is not valid for {1}.";
 string errorMessage = String.Format(CultureInfo.CurrentCulture, errorMessageTemplate,
 modelState.Value.AttemptedValue, displayName);
 modelState.Errors.Remove(error);
 modelState.Errors.Add(errorMessage);
 break;
 }
 }
 }
 }
 }
 }
}

4,建立一个VModel的基类,为该基类添加Attribute,然后在Global中添加Model和Binder的映射。

[ModelBinder(typeof (JsonNetModelBinder))]
public abstract class VEntity
{
 public virtual long Id { get; set; }
}

Global.asax中Application_Start添加代码:

 ModelBinders.Binders.Add(typeof(VEntity), new JsonNetModelBinder());

5在前端Post Json时,指定content type为application/json.net

 function PostJsonNet() {
 var jsonstr = $("#jsonstring")[0].innerHTML;
 $.ajax({
 url: "MyTest/CreateFromJsonNet",
 type: "POST",
 data: jsonstr,
 contentType: "application/json.net",
 dataType: "json",
 success: function (data) {
 alert(data);

 }
 });
 }

我们这样处理后,Client在往Server传送Json数据时,如果指定了contentType是application/json,那么就使用系统默认的方法来反序列化对象,如果是application/json.net,那么就使用Json.Net来反序列化。

示例程序下载

时间: 2024-10-25 08:29:45

在MVC中使用Json.Net序列化和反序列化Json对象的相关文章

ASP.NET中JSON的序列化和反序列化

导读:JSON是专门为浏览器中的网页上运行的JavaScript代码而设计的一种数据格式.在网站应用中使用JSON的场景越来越多,本文介绍 ASP.NET中JSON的序列化和反序列化,主要对JSON的简单介绍,ASP.NET如何序列化和反序列化的处理,在序列化和反序列化对日期时间.集合.字典的处理. 一.JSON简介 JSON(JavaScript Object Notation,JavaScript对象表示法)是一种轻量级的数据交换格式. JSON是"名值对"的集合.结构由大括号'{

PHP中SERIALIZE和JSON的序列化与反序列化操作区别分析_php技巧

本文实例讲述了PHP中SERIALIZE和JSON的序列化与反序列化操作区别.分享给大家供大家参考,具体如下: PHP中SERIALIZE和JSON序列化与反序列化区别是什么呢,对于这个问题我们可以和小编一起来看看,具体的操作细节如下所示. 在PHP中,serialize和json两种方式对一个对象或数组进行序列化或反序列化有什么区别呢? 假设一个对象和一个数组: $web = new stdClass; $web->site = 'tantengvip'; $web->owner = 'tu

ASP.NET中JSON的序列化和反序列化使用说明_实用技巧

在网站应用中使用JSON的场景越来越多,本文介绍 ASP.NET中JSON的序列化和反序列化,主要对JSON的简单介绍,ASP.NET如何序列化和反序列化的处理,在序列化和反序列化对日期时间.集合.字典的处理. 一.JSON简介 JSON(JavaScript Object Notation,JavaScript对象表示法)是一种轻量级的数据交换格式. JSON是"名值对"的集合.结构由大括号'{}',中括号'[]',逗号',',冒号':',双引号'""'组成,包含

ASPNET中JSON的序列化和反序列化的方法_实用技巧

一.JSON简介  JSON(JavaScript Object Notation,JavaScript对象表示法)是一种轻量级的数据交换格式. JSON是"名值对"的集合.结构由大括号'{}',中括号'[]',逗号',',冒号':',双引号'""'组成,包含的数据类型有Object,Number,Boolean,String,Array, NULL等. JSON具有以下的形式: 对象(Object)是一个无序的"名值对"集合,一个对象以&quo

关于asp.net中JSON的序列化和反序列化(1/4)

      json是专门为浏览器中的网页上运行的网页特效代码而设计的一种数据格式.在网站应用中使用json的场景越来越多,本文介绍asp教程.net中json的序列化和反序列化,主要对json的简单介绍,asp.net教程如何序列化和反序列化的处理,在序列化和反序列化对日期时间.集合.字典的处理.     一.json简介      json(javascript object notation,javascript对象表示法)是一种轻量级的数据交换格式.      json是"名值对&quo

一起谈.NET技术,ASP.NET 中JSON 的序列化和反序列化

JSON是专门为浏览器中的网页上运行的JavaScript代码而设计的一种数据格式.在网站应用中使用JSON的场景越来越多,本文介绍ASP.NET中JSON的序列化和反序列化,主要对JSON的简单介绍,ASP.NET如何序列化和反序列化的处理,在序列化和反序列化对日期时间.集合.字典的处理. 一.JSON简介 JSON(JavaScript Object Notation,JavaScript对象表示法)是一种轻量级的数据交换格式. JSON是"名值对"的集合.结构由大括号'{}',中

JavaScriptSerializer序列化和反序列化JSON:使用自定义JavaScriptConverter

JSON的序列化和反序列化已经成为Web开发必不可少的知识.现在常用的有System.Web.Script.Serialization下的JavaScriptSerializer来进行处理:另外一个比较常用且高效的类库是JSON.NET. 在开发一些小的应用时,由于想尽量较少项目的依赖,所以不太愿意使用JSON.NET.JavaScriptSerializer基本上能满足简单的需求,但当一个属性要序列化成别的名字时,就显得力不从心了.还有就是可能业务需要,某些属性不希望在某一个条件下进行序列化.

Json.Net系列教程 3.Json.Net序列化和反序列化设置

原文 Json.Net系列教程 3.Json.Net序列化和反序列化设置 上节补充 首先补充一点,Json.Net是支持序列化和反序列化DataTable,DataSet,Entity Framework和NHibernate的.我举例说明DataTable的序列化和反序列化.创建一个DataTable对象,如下: DataTable dt = new DataTable(); DataColumn dcName = new DataColumn("Name"); DataColumn

[asp.net]C#实现json的序列化和反序列化

在做asp.net和unity进行http通信的时候,当unity客户端发出表单请求的时候,我要将他要请求的数据以json的格式返回给客户端,让客户端来解析.服务器端这一块就涉及到json的序列化和反序列化的问题. 接下来就来举个列子,当然包括两种方法(本篇参考自:http://www.csharpwin.com/csharpspace/10822r2908.shtml) 两种方法都有例子,第一种是用泛型集合来存储的对象,然后将集合序列化一下:第二种是直接序列化的一个对象 using Syste