Как конвертировать JSON в C # общий список словарных данных, нечувствительных к регистру? [Дубликат]

В моем случае я использовал приложение 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();
    }
17
задан Bug 7 January 2014 в 22:21
поделиться

3 ответа

Одна простая идея заключалась бы в создании подкласса 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
13
ответ дан Brian Rogers 25 August 2018 в 19:57
поделиться

Создайте метод расширения, который скопирует значения из вашего регистра, чувствительного к регистру, в новый словарь, нечувствительный к регистру.

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();

Хотя это работает для меня (и мне нравится это решение из-за его простоты), обратите внимание на следующие оговорки:

  • Есть незначительные накладные расходы, вызванные копированием
  • Если у вас есть дублировать ключи в словаре (например, «cat» и «CAT»), один будет перезаписан. Вы можете легко адаптировать метод для исключения исключений в таких случаях (если хотите).
  • Мое решение не использует строгое сравнение во время десериализации, но, скорее всего, это самый простой способ получить словарь в нечувствительное к регистру состояние.
2
ответ дан Daffy Punk 25 August 2018 в 19:57
поделиться

Было бы лучше создать конвертер, который при необходимости создавал бы словарные объекты. Это то, что было разработано для 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);
7
ответ дан Jeff Mercado 25 August 2018 в 19:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: