Closed bluesky001 closed 7 years ago
See http://stackoverflow.com/a/23832417/682105:
public class NullToEmptyStringResolver : DefaultContractResolver
{
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
return type.GetProperties().Select(property => CreateProperty(property, memberSerialization)).ToList();
}
private JsonProperty CreateProperty(PropertyInfo property, MemberSerialization memberSerialization)
{
var jsonProperty = base.CreateProperty(property, memberSerialization);
jsonProperty.ValueProvider = new NullToEmptyStringValueProvider(jsonProperty.ValueProvider, property);
return jsonProperty;
}
private class NullToEmptyStringValueProvider : IValueProvider
{
private readonly IValueProvider _valueProvider;
private readonly PropertyInfo _property;
public NullToEmptyStringValueProvider(IValueProvider valueProvider, PropertyInfo property)
{
_valueProvider = valueProvider;
_property = property;
}
public object GetValue(object target)
{
var result = _valueProvider == null
? _property.GetValue(target)
: _valueProvider.GetValue(target);
if (_property.PropertyType == typeof(string) && result == null)
{
result = string.Empty;
}
return result;
}
public void SetValue(object target, object value)
{
if (_valueProvider == null)
{
_property.SetValue(target, value);
}
else
{
_valueProvider.SetValue(target, value);
}
}
}
}
public class CustomJsonSerializer : JsonSerializer
{
public CustomJsonSerializer()
{
this.Formatting = Formatting.Indented;
this.DateFormatString = "yyyy-MM-dd HH:mm:ss";
this.ReferenceLoopHandling = ReferenceLoopHandling.Serialize;
this.PreserveReferencesHandling = PreserveReferencesHandling.Objects;
this.NullValueHandling = NullValueHandling.Include;
+ this.ContractResolver = new NullToEmptyStringResolver();
}
}
thanks khellang! I use your solution, but it seems that does not work,and also return the null. Whether or not to use the wrong. or the nancy framework do not distinguish the convertaion when serialization.
@bluesky001 Where are you wiring up the CustomJsonSerializer
? Make sure you do it in ConfigureApplicationContainer
, after calling base.ConfigureApplicationContainer(container);
.
@khellang
write here.
protected override void ConfigureApplicationContainer(TinyIoCContainer container)
{
base.ConfigureApplicationContainer(container);
container.Register<JsonSerializer, CustomJsonSerializer>();
}
public class CustomJsonSerializer : JsonSerializer
{
public CustomJsonSerializer()
{
this.Formatting = Formatting.Indented;
this.DateFormatString = "yyyy-MM-dd HH:mm:ss";
this.ReferenceLoopHandling = ReferenceLoopHandling.Serialize;
this.PreserveReferencesHandling = PreserveReferencesHandling.Objects;
this.NullValueHandling = NullValueHandling.Include;
**this.ContractResolver = new NullToEmptyStringResolver();**
}
}
@khellang
using System; using System.Collections.Generic; using System.Dynamic; using System.IO; using System.Linq; using System.Reflection; using Nancy; using Nancy.Authentication.Stateless; using Nancy.Bootstrapper; using Nancy.Conventions; using Nancy.ErrorHandling; using Nancy.TinyIoc; using Nancy.ViewEngines; using Nancy.Serialization.JsonNet; using Newtonsoft.Json; using Newtonsoft.Json.Converters; using Newtonsoft.Json.Serialization; using BWFilm.Api.Common; using Nancy.Session;
namespace BWFilm.Api { public class BootStrapper:DefaultNancyBootstrapper { protected override void ConfigureRequestContainer(TinyIoCContainer container, NancyContext context) { base.ConfigureRequestContainer(container, context);
// Here we register our user mapper as a per-request singleton.
// As this is now per-request we could inject a request scoped
// database "context" or other request scoped services.
}
protected override void ConfigureConventions(NancyConventions nancyConventions)
{
base.ConfigureConventions(nancyConventions);
nancyConventions.StaticContentsConventions
.Add(StaticContentConventionBuilder.AddDirectory("static", @"Static"));
}
/// <summary>
/// Default assemblies that are ignored for autoregister
/// </summary>
private new static readonly IEnumerable<Func<Assembly, bool>> DefaultAutoRegisterIgnoredAssemblies = new Func<Assembly, bool>[]
{
asm => asm.FullName.StartsWith("Microsoft.", StringComparison.Ordinal),
asm => asm.FullName.StartsWith("System.", StringComparison.Ordinal),
asm => asm.FullName.StartsWith("System,", StringComparison.Ordinal),
asm => asm.FullName.StartsWith("CR_ExtUnitTest", StringComparison.Ordinal),
asm => asm.FullName.StartsWith("mscorlib,", StringComparison.Ordinal),
asm => asm.FullName.StartsWith("CR_VSTest", StringComparison.Ordinal),
asm => asm.FullName.StartsWith("DevExpress.CodeRush", StringComparison.Ordinal),
asm => asm.FullName.StartsWith("IronPython", StringComparison.Ordinal),
asm => asm.FullName.StartsWith("IronRuby", StringComparison.Ordinal),
asm => asm.FullName.StartsWith("xunit", StringComparison.Ordinal),
asm => asm.FullName.StartsWith("Nancy.Testing", StringComparison.Ordinal),
asm => asm.FullName.StartsWith("MonoDevelop.NUnit", StringComparison.Ordinal),
asm => asm.FullName.StartsWith("SMDiagnostics", StringComparison.Ordinal),
asm => asm.FullName.StartsWith("CppCodeProvider", StringComparison.Ordinal),
asm => asm.FullName.StartsWith("WebDev.WebHost40", StringComparison.Ordinal),
asm => asm.FullName.StartsWith("nunit", StringComparison.Ordinal),
asm => asm.FullName.StartsWith("nCrunch", StringComparison.Ordinal),
asm => asm.FullName.StartsWith("EntityFramework", StringComparison.Ordinal),
asm => asm.FullName.StartsWith("glTech.CommonLibrary.NET", StringComparison.Ordinal),
asm => asm.FullName.StartsWith("glTech.EntityFramework", StringComparison.Ordinal),
asm => asm.FullName.StartsWith("log4net", StringComparison.Ordinal),
asm => asm.FullName.StartsWith("Newtonsoft.Json", StringComparison.Ordinal),
asm => asm.FullName.StartsWith("NPOI", StringComparison.Ordinal),
asm => asm.FullName.StartsWith("Senparc.Weixin", StringComparison.Ordinal),
asm => asm.FullName.StartsWith("System.Web.Razor", StringComparison.Ordinal),
};
protected override IEnumerable<Func<Assembly, bool>> AutoRegisterIgnoredAssemblies
{
get
{
return DefaultAutoRegisterIgnoredAssemblies;
}
}
protected override void ConfigureApplicationContainer(TinyIoCContainer container)
{
base.ConfigureApplicationContainer(container);
container.Register<JsonSerializer, CustomJsonSerializer>();
}
protected override void ApplicationStartup(TinyIoCContainer container, IPipelines pipelines)
{
base.ApplicationStartup(container, pipelines);
CookieBasedSessions.Enable(pipelines);
//Repositories.ApplicationInitialize.DatabaseInitialize("BWFilm.Api", new[] { "BWFilm.Api" });
Nancy.Json.JsonSettings.MaxJsonLength = Int32.MaxValue;
Nancy.Json.JsonSettings.MaxRecursions = Int32.MaxValue;
var statelessAuthConfiguration = new StatelessAuthenticationConfiguration(nancyContext =>
{
//string authorization = nancyContext.Request.Headers["Authorization"].FirstOrDefault();
//string token = "";
//if (authorization != null && authorization.ToLower().Contains("Bearer".ToLower()) == true)
//{
// token = authorization.Replace("Bearer".ToLower(), "").Trim();
//}
//return UserDatabase.GetUserFromToken(token);
string token = nancyContext.Request.Headers.Authorization;
if (!string.IsNullOrEmpty(token))
{
return UserMapper.GetUserFromAccessToken(token);
}
else
{
return null;
}
});
StatelessAuthentication.Enable(pipelines, statelessAuthConfiguration);
//Jsonp.Disable(pipelines);//默认开启的Jsonp
}
protected override void RequestStartup(TinyIoCContainer requestContainer, IPipelines pipelines, NancyContext context)
{
base.RequestStartup(requestContainer, pipelines, context);
var maxAge = 21600;
//CORS Enable
pipelines.AfterRequest.AddItemToEndOfPipeline((ctx) =>
{
if (ctx.Request.Headers.Keys.Contains("Origin"))
{
var origins = "" + string.Join(" ", ctx.Request.Headers["Origin"]);
ctx.Response.Headers["Access-Control-Allow-Origin"] = origins;
ctx.Response.WithHeader("Access-Control-Allow-Credentials", "true")
.WithHeader("Access-Control-Allow-Methods", "POST,GET,PUT,DELETE,OPTIONS")
.WithHeader("Access-Control-Allow-Headers", "Accept, Origin, Content-type,authorization")
.WithHeader("Access-Control-Max-Age", maxAge.ToString());
}
});
}
}
public class PageNotFoundHandler : DefaultViewRenderer, IStatusCodeHandler
{
public PageNotFoundHandler(IViewFactory factory) : base(factory)
{
}
public bool HandlesStatusCode(HttpStatusCode statusCode, NancyContext context)
{
return statusCode == HttpStatusCode.NotFound||
statusCode == HttpStatusCode.Unauthorized;
}
public void Handle(HttpStatusCode statusCode, NancyContext context)
{
dynamic model = new ExpandoObject();
model.Url = context.Request.Url;
Response response = null;
switch (statusCode)
{
case HttpStatusCode.NotFound:
response = RenderView(context, "404", model);
response.StatusCode = HttpStatusCode.NotFound;
break;
case HttpStatusCode.Unauthorized:
response = RenderView(context, "401", model);
response.StatusCode = HttpStatusCode.Unauthorized;
break;
}
if (response != null)
{
context.Response = response;
}
}
}
public class CustomJsonSerializer : JsonSerializer
{
public CustomJsonSerializer()
{
//this.ContractResolver = new CamelCasePropertyNamesContractResolver();//首字母小写
this.Formatting = Formatting.Indented;
this.DateFormatString = "yyyy-MM-dd HH:mm:ss";
this.ReferenceLoopHandling = ReferenceLoopHandling.Serialize;
this.PreserveReferencesHandling = PreserveReferencesHandling.Objects;
this.NullValueHandling = NullValueHandling.Include;
this.ContractResolver = new NullToEmptyStringResolver();
}
}
public class NullToEmptyStringResolver : DefaultContractResolver
{
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
return type.GetProperties().Select(property => CreateProperty(property, memberSerialization)).ToList();
}
private JsonProperty CreateProperty(PropertyInfo property, MemberSerialization memberSerialization)
{
var jsonProperty = base.CreateProperty(property, memberSerialization);
jsonProperty.ValueProvider = new NullToEmptyStringValueProvider(jsonProperty.ValueProvider, property);
return jsonProperty;
}
private class NullToEmptyStringValueProvider : IValueProvider
{
private readonly IValueProvider _valueProvider;
private readonly PropertyInfo _property;
public NullToEmptyStringValueProvider(IValueProvider valueProvider, PropertyInfo property)
{
_valueProvider = valueProvider;
_property = property;
}
public object GetValue(object target)
{
var result = _valueProvider == null
? _property.GetValue(target)
: _valueProvider.GetValue(target);
if (_property.PropertyType == typeof(string) && result == null)
{
result = string.Empty;
}
return result;
}
public void SetValue(object target, object value)
{
if (_valueProvider == null)
{
_property.SetValue(target, value);
}
else
{
_valueProvider.SetValue(target, value);
}
}
}
}
}
Here's a functioning sample using
Nancy
Nancy.Hosting.Aspnet
(not needed for the functionality, just to make the sample run)Nancy.Serialization.JsonNet
public class Index : NancyModule
{
public Index()
{
Get["/"] = _ =>
{
return Response.AsJson(new Model());
};
}
}
public class Model
{
public string Name { get; set; }
}
public class Bootstrapper : DefaultNancyBootstrapper
{
protected override void ConfigureApplicationContainer(TinyIoCContainer container)
{
base.ConfigureApplicationContainer(container);
container.Register(new JsonSerializer
{
ContractResolver = new NullWithEmptyStringContractResolver()
});
}
}
public class NullWithEmptyStringContractResolver : DefaultContractResolver
{
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
if (property.PropertyType == typeof(string))
{
property.ValueProvider = new NullToEmptyStringValueProvider(property.ValueProvider);
}
return property;
}
private class NullToEmptyStringValueProvider : IValueProvider
{
private readonly IValueProvider provider;
public NullToEmptyStringValueProvider(IValueProvider provider)
{
this.provider = provider;
}
public object GetValue(object target)
{
return this.provider.GetValue(target) ?? string.Empty;
}
public void SetValue(object target, object value)
{
this.provider.SetValue(target, value);
}
}
}
I use the Nancy.Serialization.JsonNet and register the
JsonSerializer
:And define the class
I return a JSON object using
return Response.AsJson(msg)
in the interface, but the result containnull
values. I want to know how to convert thenull
value to''
value, thanks!Such as: