using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
[System.AttributeUsage(System.AttributeTargets.Property | System.AttributeTargets.Field, AllowMultiple = false)]
public class JsonFormatAttribute : System.Attribute
public JsonFormatAttribute(string formattingString)
this.FormattingString = formattingString;
public string FormattingString { get; set; }
public string CulturePropertyName { get; set; }
public class FormattedPropertyContractResolver : DefaultContractResolver
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
return base.CreateProperties(type, memberSerialization)
public static class JsonContractExtensions
class FormattedValueProvider : IValueProvider
readonly IValueProvider baseProvider;
readonly string formatString;
readonly IValueProvider cultureValueProvider;
public FormattedValueProvider(IValueProvider baseProvider, string formatString, IValueProvider cultureValueProvider)
this.baseProvider = baseProvider;
this.formatString = formatString;
this.cultureValueProvider = cultureValueProvider;
#region IValueProvider Members
public object GetValue(object target)
var value = baseProvider.GetValue(target);
var culture = cultureValueProvider == null ? null : (CultureInfo)cultureValueProvider.GetValue(target);
return string.Format(culture ?? CultureInfo.InvariantCulture, formatString, value);
public void SetValue(object target, object value)
throw new NotImplementedException();
public static IList<JsonProperty> AddFormatting(this IList<JsonProperty> properties)
ILookup<string, JsonProperty> lookup = null;
foreach (var jsonProperty in properties)
var attr = (JsonFormatAttribute)jsonProperty.AttributeProvider.GetAttributes(typeof(JsonFormatAttribute), false).SingleOrDefault();
IValueProvider cultureValueProvider = null;
if (attr.CulturePropertyName != null)
lookup = properties.ToLookup(p => p.UnderlyingName);
var cultureProperty = lookup[attr.CulturePropertyName].FirstOrDefault();
if (cultureProperty != null)
cultureValueProvider = cultureProperty.ValueProvider;
jsonProperty.ValueProvider = new FormattedValueProvider(jsonProperty.ValueProvider, attr.FormattingString, cultureValueProvider);
jsonProperty.PropertyType = typeof(string);
[JsonFormat("{0:c}", CulturePropertyName = "Culture")]
public decimal Cost { get; set; }
public CultureInfo Culture { get; set; }
public string SomeValue { get; set; }
public string SomeOtherValue { get; set; }
public static void Test()
var root = new RootObject
Culture = new CultureInfo("de-DE"),
SomeValue = "some value",
SomeOtherValue = "some other value",
var settings = new JsonSerializerSettings
ContractResolver = new FormattedPropertyContractResolver
var json = JsonConvert.SerializeObject(root, Formatting.Indented, settings);
public static void Main()
Console.WriteLine("Environment version: " + Environment.Version);
Console.WriteLine("Json.NET version: " + typeof(JsonSerializer).Assembly.FullName);
Console.WriteLine("Failed with unhandled exception: ");
public class AssertionFailedException : System.Exception
public AssertionFailedException() : base() { }
public AssertionFailedException(string s) : base(s) { }
public static class Assert
public static void IsTrue(bool value)
public static void IsTrue(bool value, string message)
throw new AssertionFailedException(message ?? "failed");