CSharp · Console
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
public class Program
{
public static void Main()
{
var myObject = new MyModelClass("blablabla", "<>@%#^^@!%");
var settings = new JsonSerializerSettings
{
ContractResolver = new CustomResolver(),
Formatting = Formatting.Indented
};
string json = JsonConvert.SerializeObject(myObject, settings);
Console.WriteLine(json);
}
}
public class MyModelClass
{
[JsonProperty("first_field")]
public string FirstField { get; set; }
[UrlEncode]
[JsonProperty("second_field")]
public string SecondField { get; set; }
public MyModelClass(string first, string second)
{
FirstField = first;
SecondField = second;
}
}
public class UrlEncodeAttribute : Attribute { }
public class CustomResolver : DefaultContractResolver
{
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
IList<JsonProperty> props = base.CreateProperties(type, memberSerialization);
// Find all string properties that have a [UrlEncode] attribute applied
// and attach an UrlEncodingValueProvider instance to them
foreach (JsonProperty prop in props.Where(p => p.PropertyType == typeof(string)))
{
PropertyInfo pi = type.GetProperty(prop.UnderlyingName);
if (pi != null && pi.GetCustomAttribute(typeof(UrlEncodeAttribute), true) != null)
{
prop.ValueProvider = new UrlEncodingValueProvider(pi);
}
}
return props;
}
protected class UrlEncodingValueProvider : IValueProvider
{
PropertyInfo targetProperty;
public UrlEncodingValueProvider(PropertyInfo targetProperty)
{
this.targetProperty = targetProperty;
}
// SetValue gets called by Json.Net during deserialization.
// The value parameter has the original value read from the JSON;
// target is the object on which to set the value.
public void SetValue(object target, object value)
{
targetProperty.SetValue(target, (string)value);
}
// GetValue is called by Json.Net during serialization.
// The target parameter has the object from which to read the string;
// the return value is the string that gets written to the JSON
public object GetValue(object target)
{
string value = (string)targetProperty.GetValue(target);
return System.Web.HttpUtility.UrlEncode(value);
}
}
}
// System.Web is not accessible in .Net Fiddle, so this is a shim to stand in for the HttpUtility class.
// This is for demonstration purposes only. Do not use this in production code; use the real System.Web.HttpUtility class instead.
namespace System.Web
{
public static class HttpUtility
{
public static string UrlEncode(string url)
{
StringBuilder sb = new StringBuilder();
if (!string.IsNullOrEmpty(url))
{
foreach (char c in url)
{
if (IsUrlSafeChar(c))
sb.Append(c);
else
{
sb.Append('%');
sb.Append(((int)c).ToString("X2"));
}
}
}
return sb.ToString();
}
private static bool IsUrlSafeChar(char c)
{
char[] safePunct = new char[] { '(', ')', '*', '-', '.', '!', '_' };
return ((c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') ||
(c >= '0' && c <= '9') ||
safePunct.Contains(c));
}
}
}