В моем случае я использовал приложение JEE7 JAX-RS, и следующие трюки отлично работали для меня:
@GET
@Path("{id}")
public Response getEventData(@PathParam("id") String id) throws FileNotFoundException {
InputStream inputStream = getClass().getClassLoader().getResourceAsStream("/eventdata/" + id + ".json");
JsonReader jsonReader = Json.createReader(inputStream);
return Response.ok(jsonReader.readObject()).header("Access-Control-Allow-Origin", "*").build();
}
Одна простая идея заключалась бы в создании подкласса Dictionary<string, string>
, который по умолчанию устанавливает сопоставление с StringComparer.OrdinalIgnoreCase
, а затем десериализуется в это вместо обычного словаря. Например:
class CaseInsensitiveDictionary<V> : Dictionary<string, V>
{
public CaseInsensitiveDictionary() : base(StringComparer.OrdinalIgnoreCase)
{
}
}
class Program
{
static void Main(string[] args)
{
string json = @"
{
""Foo"" :
{
""fiZZ"" : 1,
""BUzz"" : ""yo""
},
""BAR"" :
{
""dIt"" : 3.14,
""DaH"" : true
}
}";
var dict = JsonConvert.DeserializeObject<CaseInsensitiveDictionary<CaseInsensitiveDictionary<object>>>(json);
Console.WriteLine(dict["foo"]["fizz"]);
Console.WriteLine(dict["foo"]["buzz"]);
Console.WriteLine(dict["bar"]["dit"]);
Console.WriteLine(dict["bar"]["dah"]);
}
}
Выход:
1
yo
3.14
True
Создайте метод расширения, который скопирует значения из вашего регистра, чувствительного к регистру, в новый словарь, нечувствительный к регистру.
public static Dictionary<string, T> ToCaseInsensitive<T>(this Dictionary<string, T> caseSensitiveDictionary)
{
var caseInsensitiveDictionary = new Dictionary<string, T>(StringComparer.OrdinalIgnoreCase);
caseSensitiveDictionary.Keys.ToList()
.ForEach(k => caseInsensitiveDictionary[k] = caseSensitiveDictionary[k]);
return caseInsensitiveDictionary;
}
Использование:
var newDictionary = JsonConvert.DeserializeObject<Dictionary<string, string>>(value)
.ToCaseInsensitive();
Хотя это работает для меня (и мне нравится это решение из-за его простоты), обратите внимание на следующие оговорки:
Было бы лучше создать конвертер, который при необходимости создавал бы словарные объекты. Это то, что было разработано для Newtonsoft.Json.Converters.CustomCreationConverter<T>
.
Вот одна из реализаций, которые могут создавать словари, для которых требуются пользовательские сопоставления.
public class CustomComparerDictionaryCreationConverter<T> : CustomCreationConverter<IDictionary>
{
private IEqualityComparer<T> comparer;
public CustomComparerDictionaryCreationConverter(IEqualityComparer<T> comparer)
{
if (comparer == null)
throw new ArgumentNullException("comparer");
this.comparer = comparer;
}
public override bool CanConvert(Type objectType)
{
return HasCompatibleInterface(objectType)
&& HasCompatibleConstructor(objectType);
}
private static bool HasCompatibleInterface(Type objectType)
{
return objectType.GetInterfaces()
.Where(i => HasGenericTypeDefinition(i, typeof(IDictionary<,>)))
.Where(i => typeof(T).IsAssignableFrom(i.GetGenericArguments().First()))
.Any();
}
private static bool HasGenericTypeDefinition(Type objectType, Type typeDefinition)
{
return objectType.IsGenericType && objectType.GetGenericTypeDefinition() == typeDefinition;
}
private static bool HasCompatibleConstructor(Type objectType)
{
return objectType.GetConstructor(new Type[] { typeof(IEqualityComparer<T>) }) != null;
}
public override IDictionary Create(Type objectType)
{
return Activator.CreateInstance(objectType, comparer) as IDictionary;
}
}
Обратите внимание, что этот конвертер будет применяться к все словарные типы, где ключ ковариантен с T
, независимо от типа значения.
Затем использовать его:
var converters = new JsonConverter[]
{
new CustomComparerDictionaryCreationConverter<string>(StringComparer.OrdinalIgnoreCase),
};
var dict = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, object>>>(jsonString, converters);