JavaScriptserializer - Json Serialization of Enum as String

JavaScriptSerializer - JSON serialization of enum as string

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.

Serialize enum to string

The JSON formatter has very specialized behaviour when working with enumerations; the normal Data Contract attributes are ignored and it treats your enum as a number, not the more human-readable string you'd expect with other formats. Whilst this makes it easy to deal with flag-type enumerations, it makes most other types much harder to work with.

From MSDN:

Enumeration member values are treated as numbers in JSON, which is
different from how they are treated in data contracts, where they are
included as member names. For more information about the data contract
treatment, see Enumeration Types in Data Contracts.

  • For example, if you have public enum Color {red, green, blue, yellow,
    pink}
    , serializing yellow produces the number 3 and not the string
    "yellow".

  • All enum members are serializable. The EnumMemberAttribute and the
    NonSerializedAttribute attributes are ignored if used.

  • It is possible to deserialize a nonexistent enum value - for example,
    the value 87 can be deserialized into the previous Color enum even
    though there is no corresponding color name defined.

  • A flags enum is not special and is treated the same as any other enum.

The only practical way to resolve this, to allow end-users to specify a string instead of a number, is to not use the enum in your contract. Instead the practical answer is to replace your enum with a string and perform internal validation on the value such that it can be parsed into one of the valid enum representations.

Alternatively (though not for the feint of heart), you could replace the JSON formatter with your own, which would respect enumerations in the same way as other formatters.

Are there any attributes for serializing Enums as strings in Json.NET?

Just use StringEnumConverter

var actual = json.ToString(Formatting.None, 
new Newtonsoft.Json.Converters.StringEnumConverter());

EDIT

Is there no way to tell it to automatically use that converter every time you call ToString()?

JsonConvert.DefaultSettings = () => new JsonSerializerSettings() { 
Converters = new List<Newtonsoft.Json.JsonConverter>() { new Newtonsoft.Json.Converters.StringEnumConverter() }
};

var actual = JsonConvert.SerializeObject(json);

Serializing enum values in JSON (C#)

Please take look at JSON serialization of enum as string in stack overflow.
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.

Trying to convert enum to custom string name with JsonStringEnumConverter

By default, it is not supported with System.Text.Json . You can see the request for the same.

https://github.com/dotnet/runtime/issues/31081

But there is an extension library called 'Macross.Json.Extensions' where you can use JsonStringEnumMemberConverter attribute and then do what you need.

JsonConverter(typeof(JsonStringEnumMemberConverter))]
public enum DefinitionType
{
[EnumMember(Value = "UNKNOWN_DEFINITION_000")]
DefinitionUnknown
}

[TestMethod]
public void ExampleTest()
{
string Json = JonSerializer.Serialize(DefinitionType.DefinitionUnknown);

Assert.AreEqual("\"UNKNOWN_DEFINITION_000\"", Json);

DefinitionType ParsedDefinitionType = JsonSerializer.Deserialize<DefinitionType>(Json);

Assert.AreEqual(DefinitionType.DefinitionUnknown, ParsedDefinitionType);
}

You can see more at - https://github.com/Macross-Software/core/tree/develop/ClassLibraries/Macross.Json.Extensions#enumerations

Deserialise Enum From JSON String with Spaces

This is a solution for System.Text.Json

I used the Nuget package System.Text.Json.EnumExtensions

https://github.com/StefH/System.Text.Json.EnumExtensions

// you probably want these options somewhere global
private JsonSerializerOptions options;

private class TestEnumWrapper<T> where T : struct
{
public T TestEnum { get; set; }
}

public enum ObjectClass
{
[EnumMember(Value = "Rocket Body")]
RocketBody,
[EnumMember(Value = "Rocket Debris")]
RocketDebris,
[EnumMember(Value = "Rocket Fragmentation Debris")]
RocketFragmentationDebris,
[EnumMember(Value = "Rocket Mission Related Object")]
RocketMissionRelatedObject,
//etc...
}

private void CanDeserialiseEnumsWithCustomJsonStrings(Enum expected, string jsonName)
{
var json = $"{{\"TestEnum\":\"{jsonName}\"}}";

Type constructed = typeof(TestEnumWrapper<>).MakeGenericType(expected.GetType());

var res = JsonSerializer.Deserialize(json, constructed, options);
}


public void Test()
{
this.options = new JsonSerializerOptions();
options.Converters.Add(new JsonStringEnumConverterWithAttributeSupport());

var testSerialize = JsonSerializer.Serialize(new TestEnumWrapper<ObjectClass>()
{ TestEnum = ObjectClass.RocketBody }, options);

// Test Deserialize
CanDeserialiseEnumsWithCustomJsonStrings(ObjectClass.RocketBody, "Rocket Body");
}

You only have to add the new JsonStringEnumConverterWithAttributeSupport() to the JsonSerializerOptions.Converters for this to work.

If you want to use the Converter as an Attribute you have to add an parameterless constructor to the class JsonStringEnumConverterWithAttributeSupport

public JsonStringEnumConverterWithAttributeSupport() : this(namingPolicy : null, allowIntegerValues : true,
parseEnumMemberAttribute : true, parseDisplayAttribute : false, parseDescriptionAttribute : false)
{

}


Related Topics



Leave a reply



Submit