Asked  7 Months ago    Answers:  5   Viewed   179 times

I have a class that contains an enum property, and upon serializing the object using JavaScriptSerializer, my json result contains the integer value of the enumeration rather than its string "name". Is there a way to get the enum as a string in my json without having to create a custom JavaScriptConverter? Perhaps there's an attribute that I could decorate the enum 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.

 Answers

70

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.

Tuesday, June 1, 2021
 
nhunston
answered 7 Months ago
97

I faced the same issue, and included the below code to get it work.

[WebMethod]
[ScriptMethod(UseHttpGet=true ,ResponseFormat = ResponseFormat.Json)]
public void HelloWorld()
{
    Context.Response.Clear();
    Context.Response.ContentType = "application/json";
    Context.Response.Write("Hello World");
    //return "Hello World";
}

Update:

To get a pure json format, you can use javascript serializer like below.

public class WebService1 : System.Web.Services.WebService
{
    [WebMethod]
    [ScriptMethod(UseHttpGet=true ,ResponseFormat = ResponseFormat.Json)]
    public void HelloWorld()
    {
        JavaScriptSerializer js = new JavaScriptSerializer();
        Context.Response.Clear();
        Context.Response.ContentType = "application/json";           
        HelloWorldData data = new HelloWorldData();
        data.Message = "HelloWorld";
        Context.Response.Write(js.Serialize(data));


    }
}

public class HelloWorldData
{
   public String Message;
}

However this works for complex types, but string does not show any difference.

Thursday, June 3, 2021
 
Lance
answered 7 Months ago
51

You are printing the enum object. Use the .value attribute if you wanted just to print that:

print(D.x.value)

See the Programmatic access to enumeration members and their attributes section:

If you have an enum member and need its name or value:

>>>
>>> member = Color.red
>>> member.name
'red'
>>> member.value
1

You could add a __str__ method to your enum, if all you wanted was to provide a custom string representation:

class D(Enum):
    def __str__(self):
        return str(self.value)

    x = 1
    y = 2

Demo:

>>> from enum import Enum
>>> class D(Enum):
...     def __str__(self):
...         return str(self.value)
...     x = 1
...     y = 2
... 
>>> D.x
<D.x: 1>
>>> print(D.x)
1
Tuesday, June 22, 2021
 
codingb
answered 6 Months ago
27

This is happening because JsonConvert.SerializeObject applies the incoming settings on top of the default settings, by internally calling JsonSerializer.CreateDefault(JsonSerializerSettings settings). I don't know if/where this behavior is documented, but it's visible in the source code. Thus the default list of converters will be used in addition to the empty list of locally specified converters, meaning the default StringEnumConverter will get used.

You have a couple options to work around this:

  1. Construct the JsonSerializer yourself without using the default settings:

    public static class JsonExtensions
    {
        public static string SerializeObjectNoDefaultSettings(object value, Formatting formatting, JsonSerializerSettings settings)
        {
            var jsonSerializer = JsonSerializer.Create(settings);
            jsonSerializer.Formatting = formatting;
    
            StringBuilder sb = new StringBuilder(256);
            StringWriter sw = new StringWriter(sb, CultureInfo.InvariantCulture);
            using (JsonTextWriter jsonWriter = new JsonTextWriter(sw))
            {
                jsonWriter.Formatting = jsonSerializer.Formatting;
                jsonSerializer.Serialize(jsonWriter, value);
            }
    
            return sw.ToString(); 
        }
    }
    

    And then use it like:

    var json = JsonExtensions.SerializeObjectNoDefaultSettings(value, Formatting.None, new JsonSerializerSettings());
    
  2. Supersede the default StringEnumConverter with one that does not serialize enums as strings, for instance:

    public class IntegerEnumConverter : StringEnumConverter
    {
        public override bool CanRead { get { return false; } }
    
        public override bool CanWrite { get { return false; } }
    }
    

    And then use it like:

    var json = JsonConvert.SerializeObject(value, Formatting.None, new JsonSerializerSettings { Converters = new JsonConverter[] { new IntegerEnumConverter() } });
    

    The locally specified converter will be picked up in preference to the default converter.

Temporarily nulling out the JsonConvert.DefaultSettings would be a bad idea since it would not be thread-safe.

Monday, August 23, 2021
 
TecHunter
answered 4 Months ago
43

I got the solution as follow.

JsonConvert.SerializeObject(this, Formatting.None, new IsoDateTimeConverter() {
    DateTimeFormat = "yyyy-MM-dd hh:mm:ss"
});

Here is the answer:

how to force netwtonsoft json serializer to serialize datetime property to string?

Saturday, October 30, 2021
 
bishop
answered 1 Month ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :
 
Share