. NET - JSON serializacja enum jako string
Mam klasę, która zawiera właściwość enum
i po serializacji obiektu za pomocą JavaScriptSerializer
, mój wynik json zawiera wartość całkowitą wyliczenia, a nie jego string
"Nazwa". Czy istnieje sposób, aby uzyskać enum jako string
w moim json bez konieczności tworzenia niestandardowego JavaScriptConverter
? Może jest jakiś atrybut, którym mógłbym ozdobić enum
definicję lub właściwość obiektu?
Jako przykład:
enum Gender { Male, Female }
class Person
{
int Age { get; set; }
Gender Gender { get; set; }
}
Pożądany wynik json:
{ "Age": 35, "Gender": "Male" }
20 answers
Nie istnieje żaden specjalny atrybut, którego możesz użyć. JavaScriptSerializer
serializuje enums
do ich wartości liczbowych, a nie do ich reprezentacji łańcuchowej. Aby serializować enum
jako nazwę zamiast wartości numerycznej, należy użyć niestandardowej serializacji.
Edit:
Jak zauważył @OmerBakhari JSON.net obejmuje ten przypadek użycia (poprzez atrybut [JsonConverter(typeof(StringEnumConverter))]
) i wiele innych nie obsługiwanych przez wbudowane serializery. NET. Oto link porównujący funkcje i funkcjonalności serializery .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-25 12:20:39
I have found that Json.NET dostarcza dokładną funkcjonalność, której szukam z atrybutem StringEnumConverter
:
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
[JsonConverter(typeof(StringEnumConverter))]
public Gender Gender { get; set; }
Więcej szczegółów na stronie StringEnumConverter
Dokumentacja .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-06 17:23:16
Dodaj poniżej do swojej globalnej.asax dla serializacji JSON c # enum jako string
HttpConfiguration config = GlobalConfiguration.Configuration;
config.Formatters.JsonFormatter.SerializerSettings.Formatting =
Newtonsoft.Json.Formatting.Indented;
config.Formatters.JsonFormatter.SerializerSettings.Converters.Add
(new Newtonsoft.Json.Converters.StringEnumConverter());
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-09 18:06:33
@Iggy answer ustawia serializację JSON w c# enum jako ciąg znaków Tylko dla ASP.NET (Web API i tak).
Ale aby to działało również z serializacją ad hoc, dodaj following do swojej klasy startowej (jak Global.ASAX Application_Start)
//convert Enums to Strings (instead of Integer) globally
JsonConvert.DefaultSettings = (() =>
{
var settings = new JsonSerializerSettings();
settings.Converters.Add(new StringEnumConverter { CamelCaseText = true });
return settings;
});
Więcej informacji na Json.NET Strona
Dodatkowo, aby Twój członek enum mógł serializować / deserializować do / z określonego tekstu, użyj
System.Runtime.Serializacja.EnumMember
Atrybut, TAK:
public enum time_zone_enum
{
[EnumMember(Value = "Europe/London")]
EuropeLondon,
[EnumMember(Value = "US/Alaska")]
USAlaska
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-24 11:24:47
Nie byłem w stanie zmienić modelu źródłowego jak w górnej odpowiedzi (z @ob.), a ja nie chciałem rejestrować go globalnie jak @Iggy. Więc połączyłem https://stackoverflow.com/a/2870420/237091 i @ Iggy ' s https://stackoverflow.com/a/18152942/237091 aby umożliwić włączenie konwertera ciągu znaków enum podczas samego polecenia SerializeObject:
Newtonsoft.Json.JsonConvert.SerializeObject(
objectToSerialize,
Newtonsoft.Json.Formatting.None,
new Newtonsoft.Json.JsonSerializerSettings()
{
Converters = new List<Newtonsoft.Json.JsonConverter> {
new Newtonsoft.Json.Converters.StringEnumConverter()
}
})
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:26
Można to łatwo zrobić, dodając ScriptIgnore
atrybut do właściwości Gender
, co powoduje, że nie jest serializowana, i dodanie właściwości GenderString
, która robi otrzymuje serializację:
class Person
{
int Age { get; set; }
[ScriptIgnore]
Gender Gender { get; set; }
string GenderString { get { return Gender.ToString(); } }
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-21 13:27:09
Ta wersja odpowiedzi Stephena nie zmienia nazwy w JSON:
[DataContract(
Namespace =
"http://schemas.datacontract.org/2004/07/Whatever")]
class Person
{
[DataMember]
int Age { get; set; }
Gender Gender { get; set; }
[DataMember(Name = "Gender")]
string GenderString
{
get { return this.Gender.ToString(); }
set
{
Gender g;
this.Gender = Enum.TryParse(value, true, out g) ? g : Gender.Male;
}
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:26
Oto odpowiedź dla newtonsoft.json
enum Gender { Male, Female }
class Person
{
int Age { get; set; }
[JsonConverter(typeof(StringEnumConverter))]
Gender Gender { get; set; }
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-21 09:47:56
Oto proste rozwiązanie, które serializuje C# enum po stronie serwera do JSON i używa wyniku do wypełnienia elementu po stronie klienta <select>
. Działa to zarówno dla enum prostych, jak i enum bitflag.
Dodałem rozwiązanie end-to-end, ponieważ myślę, że większość ludzi, którzy chcą serializować C# enum do JSON, prawdopodobnie będzie go używać do wypełnienia <select>
rozwijanej listy.
Idzie:
Przykład Enum
public enum Role
{
None = Permission.None,
Guest = Permission.Browse,
Reader = Permission.Browse| Permission.Help ,
Manager = Permission.Browse | Permission.Help | Permission.Customise
}
Złożone enum, które wykorzystuje bitowe or do generowania system uprawnień. Więc nie można polegać na prostym indeksie [0,1,2..] dla wartości całkowitej enum.
Strona Serwera-C #
Get["/roles"] = _ =>
{
var type = typeof(Role);
var data = Enum
.GetNames(type)
.Select(name => new
{
Id = (int)Enum.Parse(type, name),
Name = name
})
.ToArray();
return Response.AsJson(data);
};
Powyższy kod wykorzystuje framework NancyFX do obsługi żądania Get. Używa metody pomocniczej Response.AsJson()
Nancy - ale nie martw się, możesz użyć dowolnego standardowego formatera JSON, ponieważ enum zostało już rzutowane do prostego anonimowego typu gotowego do serializacji.
Wygenerowany JSON
[
{"Id":0,"Name":"None"},
{"Id":2097155,"Name":"Guest"},
{"Id":2916367,"Name":"Reader"},
{"Id":4186095,"Name":"Manager"}
]
Strona Klienta - CoffeeScript
fillSelect=(id, url, selectedValue=0)->
$select = $ id
$option = (item)-> $ "<option/>",
{
value:"#{item.Id}"
html:"#{item.Name}"
selected:"selected" if item.Id is selectedValue
}
$.getJSON(url).done (data)->$option(item).appendTo $select for item in data
$ ->
fillSelect "#role", "/roles", 2916367
HTML przed
<select id="role" name="role"></select>
HTML po
<select id="role" name="role">
<option value="0">None</option>
<option value="2097155">Guest</option>
<option value="2916367" selected="selected">Reader</option>
<option value="4186095">Manager</option>
</select>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-22 14:13:31
Kombinacja Omer Bokhari i odpowiedzi Uriego jest zawsze moim rozwiązaniem, ponieważ wartości, które chcę podać, zwykle różnią się od tego, co mam w moim enum, szczególnie, że chciałbym móc zmienić moje enum, jeśli muszę.
Więc jeśli ktoś jest zainteresowany, to jest to coś takiego:
public enum Gender
{
[EnumMember(Value = "male")]
Male,
[EnumMember(Value = "female")]
Female
}
class Person
{
int Age { get; set; }
[JsonConverter(typeof(StringEnumConverter))]
Gender Gender { get; set; }
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-16 10:52:58
Możesz utworzyć JsonSerializerSettings za pomocą wywołania JsonConverter.SerializeObject jak poniżej:
var result = JsonConvert.SerializeObject
(
dataObject,
new JsonSerializerSettings
{
Converters = new [] {new StringEnumConverter()}
}
);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-17 12:29:49
Możesz również dodać konwerter do swojego JsonSerializer
, jeśli nie chcesz używać atrybutu JsonConverter
:
string SerializedResponse = JsonConvert.SerializeObject(
objToSerialize,
new Newtonsoft.Json.Converters.StringEnumConverter()
);
To będzie działać dla każdego enum
widzi podczas tej serializacji.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-13 13:04:35
Dla. Net Core Web Api : -
public void ConfigureServices(IServiceCollection services)
{
...
services.AddJsonFormatters(f => f.Converters.Add(new StringEnumConverter()));
...
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-30 22:47:24
Zauważyłem, że nie ma odpowiedzi na serializację, gdy istnieje atrybut opisu.
Oto moja implementacja, która wspiera atrybut Description.
public class CustomStringEnumConverter : Newtonsoft.Json.Converters.StringEnumConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
Type type = value.GetType() as Type;
if (!type.IsEnum) throw new InvalidOperationException("Only type Enum is supported");
foreach (var field in type.GetFields())
{
if (field.Name == value.ToString())
{
var attribute = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) as DescriptionAttribute;
writer.WriteValue(attribute != null ? attribute.Description : field.Name);
return;
}
}
throw new ArgumentException("Enum not found");
}
}
Enum:
public enum FooEnum
{
// Will be serialized as "Not Applicable"
[Description("Not Applicable")]
NotApplicable,
// Will be serialized as "Applicable"
Applicable
}
Użycie:
[JsonConverter(typeof(CustomStringEnumConverter))]
public FooEnum test { get; set; }
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-05 08:50:47
To stare pytanie, ale pomyślałem, że na wszelki wypadek się dołożymy. W moich projektach używam osobnych modeli dla dowolnych żądań Json. Model ma zazwyczaj taką samą nazwę jak obiekt domain z przedrostkiem "Json". Modele są mapowane za pomocą AutoMapper . Jeśli model json deklaruje właściwość string, która jest klasą enum na domenie, AutoMapper rozwiąże swoją prezentację string.
Jeśli się zastanawiasz, potrzebuję osobnych modeli dla klas serializowanych Json, ponieważ wbudowane serializer wymyśla odniesienia okrągłe inaczej.
Mam nadzieję, że to komuś pomoże.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-27 15:58:04
Możesz użyć Javascriptconvertera, aby to osiągnąć za pomocą wbudowanego Javascriptserializera. Konwertując swój enum na Uri możesz zakodować go jako ciąg znaków.
Opisałem, jak to zrobić dla dat, ale może być również używany do wyliczeń.
Http://blog.calyptus.eu/seb/2011/12/custom-datetime-json-serialization/
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-28 10:29:30
Na wszelki wypadek, gdyby ktoś uznał powyższe za niewystarczające, skończyło się na tym przeciążeniu:
JsonConvert.SerializeObject(objToSerialize, Formatting.Indented, new Newtonsoft.Json.Converters.StringEnumConverter())
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-27 08:35:49
ASP.NET Droga Podstawowa:
public class Startup
{
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddMvc().AddJsonOptions(options =>
{
options.SerializerSettings.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());
});
}
}
Https://gist.github.com/regisdiogo/27f62ef83a804668eb0d9d0f63989e3e
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-19 08:08:26
Zebrałem wszystkie fragmenty tego rozwiązania za pomocą biblioteki Newtonsoft.Json
. Rozwiązuje problem enum, a także znacznie poprawia obsługę błędów i działa w usługach hostowanych IIS. Jest to dość dużo kodu, więc możesz go znaleźć na Githubie tutaj: https://github.com/jongrant/wcfjsonserializer/blob/master/NewtonsoftJsonFormatter.cs
Musisz dodać kilka wpisów do swojego Web.config
aby go uruchomić, możesz zobaczyć przykładowy plik proszę.:
https://github.com/jongrant/wcfjsonserializer/blob/master/Web.config
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-12 10:45:29
new JavaScriptSerializer().Serialize(
(from p
in (new List<Person>() {
new Person()
{
Age = 35,
Gender = Gender.Male
}
})
select new { Age =p.Age, Gender=p.Gender.ToString() }
).ToArray()[0]
);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-19 15:23:17