Вопрос по c#, json, enums, json.net – Json.net Конвертер пользовательских перечислений

3

В настоящее время я использую Json.net для использования JSON в моем приложении. API, который я использую, отправляет мне определенный строковый формат для enum, например:

Для перечисления типаTemperatureType со значениямиfahrenheit, Celcius

Значение JSON:{"result":["TemperatureType_fahrenheit","TemperatureType_Celcius"]}

Я хотел бы использовать конвертер, чтобы напрямую управлять им, чтобы получитьIList<TemperatureType> но также работает для других типов перечислений.

У кого-нибудь есть идея?

Я пытаюсь использовать пользовательский JsonConverter:

  if (reader.TokenType == JsonToken.String && reader.Value != null)
  {
      string value = reader.Value.ToString();
      var splitValues = value.Split('_');
      if (splitValues.Length == 2)
      {
         var type = Type.GetType(splitValues[0]);
         return Enum.Parse(type, splitValues[1]);
      }
  }

Проблема в свойстве GetType, потому что у меня нет параметров, указывающих на нужный тип, и нет пространства имен

это всего лишь часть моего ответа Json (одно из значений, содержащихся в json). Что касается оформления, я видел поток, но я не хочу добавлять декоратор строк, если это возможно, чтобы избежать ошибок разработчиков. Tchoupi
1) Ваш JSON кажется недействительным. Не должно ли быть{" в начале? 2) это дубликатКак украсить JSON.NET StringEnumConverter? dbc

Ваш Ответ

1   ответ
7

Тип enum являетсяobjectType аргументReadJson, Тем не менее, несколько моментов:

  1. Вы должны работать с типами enullable enum.
  2. Вы должны справиться[Flag] Перечисления. Json.NET записывает их как разделенные запятыми списки значений.
  3. Вам нужно обработать случай перечисления с недопустимым значением. Json.NET записывает их как числовые значения, когдаStringEnumConverter.AllowIntegerValues == true и выдает исключение в противном случае.

Вот подклассStringEnumConverter это обрабатывает эти случаи, вызывая базовый класс, а затем добавляя или удаляя префикс типа, когда это уместно:

public class TypePrefixEnumConverter : StringEnumConverter
{
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        bool isNullable = (Nullable.GetUnderlyingType(objectType) != null);
        Type enumType = (Nullable.GetUnderlyingType(objectType) ?? objectType);
        if (!enumType.IsEnum)
            throw new JsonSerializationException(string.Format("type {0} is not a enum type", enumType.FullName));
        var prefix = enumType.Name + "_";

        if (reader.TokenType == JsonToken.Null)
        {
            if (!isNullable)
                throw new JsonSerializationException();
            return null;
        }

        // Strip the prefix from the enum components (if any).
        var token = JToken.Load(reader);
        if (token.Type == JTokenType.String)
        {
            token = (JValue)string.Join(", ", token.ToString().Split(',').Select(s => s.Trim()).Select(s => s.StartsWith(prefix) ? s.Substring(prefix.Length) : s).ToArray());
        }

        using (var subReader = token.CreateReader())
        {
            while (subReader.TokenType == JsonToken.None)
                subReader.Read();
            return base.ReadJson(subReader, objectType, existingValue, serializer); // Use base class to convert
        }
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var array = new JArray();
        using (var tempWriter = array.CreateWriter())
            base.WriteJson(tempWriter, value, serializer);
        var token = array.Single();

        if (token.Type == JTokenType.String && value != null)
        {
            var enumType = value.GetType();
            var prefix = enumType.Name + "_";
            token = (JValue)string.Join(", ", token.ToString().Split(',').Select(s => s.Trim()).Select(s => (!char.IsNumber(s[0]) && s[0] != '-') ? prefix + s : s).ToArray());
        }

        token.WriteTo(writer);
    }
}

Затем вы можете использовать его везде, где вы могли бы использоватьStringEnumConverter, например:

        var settings = new JsonSerializerSettings { Converters = new JsonConverter[] { new TypePrefixEnumConverter() } };
        var json = JsonConvert.SerializeObject(myClass, Formatting.Indented, settings);
это здорово, именно то, что я искал, и теперь я понимаю, более точно, JSON Converter Спасибо ! Tchoupi

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