JavaScriptSerializer - JSON serialization of enum as string
Solution 1
No there is no special attribute you can use. JavaScriptSerializer
serializes enums
to their numeric values and not their string representation. You would need to use custom serialization to serialize the enum
as its name instead of numeric value.
If you can use JSON.Net instead of JavaScriptSerializer
than see answer on this question provided by OmerBakhari: JSON.net covers this use case (via the attribute [JsonConverter(typeof(StringEnumConverter))]
) and many others not handled by the built in .net serializers. Here is a link comparing features and functionalities of the serializers.
Solution 2
I have found that Json.NET provides the exact functionality I'm looking for with a StringEnumConverter
attribute:
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
[JsonConverter(typeof(StringEnumConverter))]
public Gender Gender { get; set; }
More details at available on StringEnumConverter
documentation.
There are other places to configure this converter more globally:
-
enum itself if you want enum always be serialized/deserialized as string:
[JsonConverter(typeof(StringEnumConverter))] enum Gender { Male, Female }
-
In case anyone wants to avoid attribute decoration, you can add the converter to your JsonSerializer (suggested by Bjørn Egil):
serializer.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());
and it will work for every enum it sees during that serialization (suggested by Travis).
-
or JsonConverter (suggested by banana):
JsonConvert.SerializeObject(MyObject, new Newtonsoft.Json.Converters.StringEnumConverter());
Additionally you can control casing and whether numbers are still accepted by using StringEnumConverter(NamingStrategy, Boolean) constructor.
Solution 3
Add the below to your global.asax for JSON serialization of c# enum as 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());
Solution 4
@Iggy answer sets JSON serialization of c# enum as string only for ASP.NET (Web API and so).
But to make it work also with ad hoc serialization, add following to your start class (like 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;
});
More information on the Json.NET page
Additionally, to have your enum member to serialize/deserialize to/from specific text, use the
System.Runtime.Serialization.EnumMember
attribute, like this:
public enum time_zone_enum
{
[EnumMember(Value = "Europe/London")]
EuropeLondon,
[EnumMember(Value = "US/Alaska")]
USAlaska
}
Solution 5
I wasn't able to change the source model like in the top answer (of @ob.), and I didn't want to register it globally like @Iggy. So I combined https://stackoverflow.com/a/2870420/237091 and @Iggy's https://stackoverflow.com/a/18152942/237091 to allow setting up the string enum converter on during the SerializeObject command itself:
Newtonsoft.Json.JsonConvert.SerializeObject(
objectToSerialize,
Newtonsoft.Json.Formatting.None,
new Newtonsoft.Json.JsonSerializerSettings()
{
Converters = new List<Newtonsoft.Json.JsonConverter> {
new Newtonsoft.Json.Converters.StringEnumConverter()
}
})
Omer Bokhari
Updated on May 11, 2022Comments
-
Omer Bokhari almost 2 years
I have a class that contains an
enum
property, and upon serializing the object usingJavaScriptSerializer
, my json result contains the integer value of the enumeration rather than itsstring
"name". Is there a way to get the enum as astring
in my json without having to create a customJavaScriptConverter
? Perhaps there's an attribute that I could decorate theenum
definition, or object property, with?As an example:
enum Gender { Male, Female } class Person { int Age { get; set; } Gender Gender { get; set; } }
Desired JSON result:
{ "Age": 35, "Gender": "Male" }
Ideally looking for answer with built-in .NET framework classes, if not possible alternatives (like Json.net) are welcome.
-
Stephen Kennedy almost 9 yearsChange to which? The highest upvoted answer doesn't actually answer the question - yes it is useful in other contexts, hence the votes, but it is of no practicable use whatsoever if you are stuck with the MS JavaScriptSerializer, as essentially you are if using page methods and, most importantly, as required by the question. The accepted answer says its not possible. My answer whilst a bit of a hack gets the job done.
-
-
RredCat over 13 yearsFollow by link for description how to use it in asp.net mvc application james.newtonking.com/archive/2008/10/16/…
-
CAD bloke over 12 yearsHere is the link to that function: james.newtonking.com/projects/json/help/html/…
-
KCD over 11 yearsI believe this is valid for the
DataContractJsonSerializer
notJavaScriptSerializer
-
ledragon about 11 yearsNice to learn that feature of Automapper ;-) [ScriptIgnore] attribute will remove circular references
-
Ales Potocnik Hahonina about 11 yearsOh. Didn't know about the attribute. Thanks! Would you use that on your Pocos? I've resorted to using MetadataType definitions for any Poco attributes just to keep them clean. Would the attribute still work via meta data?
-
RredCat about 11 yearsLet me try to explain. This solution isn't correct according to design paters. You modified the model according to view purpose. But model has to contain data only and doesn't care about presentations. You have to move this functionality on the other layer.
-
Dima almost 11 yearsActually, Model is used to pass data from controller, ant it is controller, who does not care about presentation. Introduction of automated property (GenderString here) does not break controller, which still uses Gender property, but provides easy access for a view. Logical solution.
-
The Senator over 10 yearsSimple and solves the problem for me using native .NET framework serializers.
-
Iggy over 10 yearsHttpConfiguration config = GlobalConfiguration.Configuration; config.Formatters.JsonFormatter.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented; config.Formatters.JsonFormatter.SerializerSettings.Converters.Add (new Newtonsoft.Json.Converters.StringEnumConverter());
-
Mariano Desanze over 10 years@RredCat There is nothing wrong with having view-specific properties in the "view model". IMHO the mistake would be not to split the view model from the domain model: blogs.msdn.com/b/simonince/archive/2010/01/26/…
-
Daniel Gruszczyk over 10 yearsbest solution for me as I am not allowed to use 3rd party libraries (ISO complience issues)
-
MEMark over 10 years@RredCat, even if it were incorrect according to some pattern, the OP says nothing about this, so this is indeed a correct answer. (Even if I philosophically may agree with your point.)
-
sq33G over 10 yearsFor some reason, I'm not getting this to work. Fiddler shows a stubborn 2 rather than 'Warning', even with this in place. Also - any reason why to change the
Formatting
toIndented
? -
Odys about 10 yearsIt is useful to note by default ASP.NET MVC doesn't use Json.Net as json serializer and one need to either extend
Controller
or manually override every serialization. -
Greg Z. about 10 yearsThe third line from this example was added to the App_start/webapiconfig.cs file and did a trick for me in an ASP.NET Web API 2.1 project to return strings for enum values in REST (json fomat) calls.
-
Bogdan over 9 yearsthis also woks nice if you have a property like this List<someEnumType>
-
Stephen Kennedy over 9 yearsThis isn't for the type of serialiser in the question of course. JavaScriptSerializer serialises everything which isn't ignored, whereas DataContractJsonSerializer requires DataMember attributes. Thanks for the shout out but please note you spelt my name wrong :)
-
crush over 9 yearsIs it possible to do this with the
DataContractJsonSerializer
? -
user3285954 almost 9 years@Stephen Kennedy: Why keep both properties in this case? Why not have string Gender only?
-
Stephen Kennedy almost 9 years@user3285954 GenderString is read only (no setter). You need to store the value somewhere. It could of course be a private property/field.
-
user3285954 almost 9 years@Stephen Kennedy The question still stands: what is the benefit of having both values in a view model if only the string is used?
-
Stephen Kennedy almost 9 years@user3285954 It's a cheap way to achieve the required serialisation using the built-in JavaScriptSerializer, i.e. it answers the question. Only the string will be serialized so I really don't see the problem. If you want elegance use Json.Net; if you need a quick workaround to the issue posed and want to use asmx or page methods with the built-in serializer, here is the answer.
-
user3285954 almost 9 years@Stephen Kennedy How is creating an additional property and using an attribute cheaper than changing property type to string? I mean what is the benefit to store the same data in the same object twice when one of them is ignored? Not to mention that this requires an awkward name to avoid conflict.
-
Stephen Kennedy almost 9 years@user3285954 The value is only stored once, as an enum, with the rationale that the enum property may be referenced elsewhere in the solution. It is also serialised only once, as a string, which is done on the fly. This solution has worked well for me and 26 upvoters. Feel free to modify the approach e.g. to a string property only if that suits you better (and see also myehman's variation of my answer). Just bear in mind this is a practical workaround for a slightly inadequate piece of MS functionality, not a design principle! I won't be commenting any further. Thanks.
-
Basic almost 9 yearsOf course, deserializing using this method will cause problems since the property is readonly
-
Mike Mooney almost 9 yearsThe pedantically absurd bike-shedding in this comment thread is fascinating.
-
Mike Caron over 8 yearsThe actual answer to @user3285954's question is that the enum is constrained to a limited set of values, while the string is not. Depending on whether you need to pass values back, this may or may not be sufficient.
-
Anestis Kivranoglou about 8 yearsIs there a way to Set this property only per Request Scope?
-
BeemerGuy almost 8 years@Fabzter -- your solution worked with me using Newtonsoft's Json
-
BrainSlugs83 over 7 years@AnestisKivranoglou just make use a custom json serializer per request with it's own settings.
-
BrainSlugs83 over 7 years@BornToCode Json.NET is the serializer that ASP.NET uses by default.
-
BornToCode over 7 years@BrainSlugs83 - The question was about using JavaScriptSerializer, not Json.NET (and if you look at the revisions history you'll see that there was an edit to clarify that), if you use JavaScriptSerializer the attribute
JsonConverter
is not going to work. -
user3791372 over 7 yearsthe first serializer setting of indented is unrelated to the op question.
-
Poulad over 6 yearsThank you! I was just looking for
[EnumMember]
. -
ᴍᴀᴛᴛ ʙᴀᴋᴇʀ over 6 yearsYou'll need references for
System.Net.Http.Formatting
,System.Web.Http
andSystem.Web.Http.WebHost
. -
Seafish over 6 yearsYou can customize the converter (say, for
camelCase
output):new StringEnumConverter { CamelCaseText = true }
-
infl3x over 6 yearsIf this is the one from the
Microsoft.AspNetCore.Mvc.Formatters.Json
NuGet package, it seems to only be an extension method onIMvcCoreBuilder
, notIMvcBuilder
. So it's used likeservices.AddMvcCore().AddJsonFormatters(f => f.Converters.Add(new StringEnumConverter()));
. -
Peet about 6 yearsThank you for this answer, helped me a lot! If you want to define your enums in PascalCase, but you want it to be serialized in camelCase then you need to add
true
to your JsonConverter type like this:[JsonConverter(typeof(StringEnumConverter), true)]
-
Prolog over 5 yearsI was using
JsonPropertyAttribute
for enum members and it is working for simple deserializtion tasks. Sadly, during manual tweaks withJToken
s it gets ignored. HappillyEnumMemberAttribute
works like a charm. Thanks! -
CMS over 5 yearsas always Newtonsoft.Json does not disappoint, then i wonder why is XML still used 😌
-
Sbu about 5 yearsThe constructor now takes a naming strategy type (the bool param
camelCaseText
being deprecated), so if you want e.g. camelCase :new StringEnumConverter(typeof(CamelCaseNamingStrategy))
-
Dirk Brockhaus almost 5 yearsThis is a good solution for a current use case of mine: I don't want to change the serializers defaults and I have problems using attributes, because my properties are of type IList<EnumType>.
-
fiat over 4 yearsThe
CamelCaseText
property is now marked obsolete. New way to instantiate the converter:new StringEnumConverter(new CamelCaseNamingStrategy())
-
Alexei Levenkov over 4 yearsOmer Bokhari: if you agree with my edit on the answer consider to flag all comments as "other: remove all comments as they are inlined in the post". (Definitely mark this as "no longer needed" when you read it).
-
ryanwebjackson almost 4 years"Json.NET is the serializer that ASP.NET uses by default" -- This was not true when the question was asked or answered. (but the most important thing is the clarity of the answer)
-
laventnc over 3 yearsstill relatively new to .NET but I've been told to avoid try catch expressions for performance reasons. Wouldn't a serializer be a bad place to use one if that is the case?
-
Dusty over 3 years@laventnc The try...catch itself isn't going to impact performance, but if exception is raised, there's performance overhead for that. The point of this implementation is fault tolerance ... not allowing a single unknown enum value to prevent your entire JSON payload from deserializing. Compare the base
StringEnumConveter
: the exception would still be raised, but it will cause the whole deserialization process to fail (and its likely caught somewhere farther up the stack). Whether you need this kind of fault tolerance is an artifact of your use case(s). -
developer learn999 over 3 yearsthe JsonConvert you place in ConfigureServices or in Configure in NET CORE 2?
-
John Washam about 3 yearsAs @Bogdan mentioned, this was the fix for me to make a
List<AnEnumType>
property serialize with the string value of each Enum value instead of the number value. -
Noman_1 almost 3 years[JsonConverter(typeof(StringEnumConverter))] is for newtonsoft
-
jolySoft almost 3 yearsNice and clean.
-
Dean almost 2 yearsThe correct library to use here is actually:
using System.Text.Json.Serialization;