JavaScriptSerializer - Tuần tự hóa JSON của enum dưới dạng chuỗi


1162

Tôi có một lớp có chứa một thuộc enumtính và khi tuần tự hóa đối tượng bằng cách sử dụng JavaScriptSerializer, kết quả json của tôi chứa giá trị nguyên của phép liệt kê thay vì string"tên" của nó . Có cách nào để có được enum như stringtrong json của tôi mà không phải tạo một tùy chỉnh JavaScriptConverterkhông? Có lẽ có một thuộc tính mà tôi có thể trang trí enumđịnh nghĩa, hoặc thuộc tính đối tượng, với?

Ví dụ:

enum Gender { Male, Female }

class Person
{
    int Age { get; set; }
    Gender Gender { get; set; }
}

Kết quả mong muốn json:

{ "Age": 35, "Gender": "Male" }

Lý tưởng tìm kiếm câu trả lời với các lớp .NET framework tích hợp, nếu không thể thay thế (như Json.net) đều được chào đón.


8
Thay đổi thành gì? Câu trả lời được đánh giá cao nhất không thực sự trả lời câu hỏi - vâng, nó rất hữu ích trong các bối cảnh khác, do đó, phiếu bầu, nhưng không thể sử dụng bất cứ điều gì nếu bạn bị mắc kẹt với MS JavaScriptSerializer, vì về cơ bản bạn đang sử dụng các phương thức trang và , quan trọng nhất, theo yêu cầu của câu hỏi. Câu trả lời được chấp nhận nói rằng nó không thể. Câu trả lời của tôi trong khi một chút hack đã hoàn thành công việc.
Stephen Kennedy

Câu trả lời:


376

Không có không có thuộc tính đặc biệt bạn có thể sử dụng. JavaScriptSerializertuần tự hóa enumscác giá trị số của chúng và không biểu diễn chuỗi của chúng. Bạn sẽ cần sử dụng tuần tự hóa tùy chỉnh để tuần tự hóa enumnhư tên của nó thay vì giá trị số.


Nếu bạn có thể sử dụng JSON.Net thay vì JavaScriptSerializerxem câu trả lời cho câu hỏi này do OmerBakhari cung cấp : JSON.net bao gồm trường hợp sử dụng này (thông qua thuộc tính [JsonConverter(typeof(StringEnumConverter))]) và nhiều câu hỏi khác không được xử lý bởi các bộ nối tiếp .net tích hợp. Dưới đây là một liên kết so sánh các tính năng và chức năng của các serial serial .


7
@Fabzter - giải pháp của bạn đã làm việc với tôi bằng cách sử dụng Json của
Newtonsoft

1
@BornToCode Json.NET là trình tuần tự hóa mà ASP.NET sử dụng theo mặc định.
BrainSlugs83

12
@ BrainSlugs83 - Câu hỏi là về việc sử dụng JavaScriptSerializer, không phải Json.NET (và nếu bạn nhìn vào lịch sử sửa đổi, bạn sẽ thấy rằng có một chỉnh sửa để làm rõ điều đó), nếu bạn sử dụng JavaScriptSerializer thì thuộc tính JsonConvertersẽ không hoạt động.
Sinh ra ToCode

50
Vui lòng xóa câu trả lời này dưới dạng câu trả lời được chấp nhận vì nó không giải quyết được vấn đề, câu trả lời dưới đây với hơn 1000 lượt lên.
MHGameWork

bạn có thể làm phiền tôi không
Yongqiang Chen

2101

Tôi đã thấy rằng Json.NET cung cấp chức năng chính xác mà tôi đang tìm kiếm với một StringEnumConverterthuộc tính:

using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

[JsonConverter(typeof(StringEnumConverter))]
public Gender Gender { get; set; }

Thêm chi tiết có sẵn trên StringEnumConvertertài liệu .

Có những nơi khác để định cấu hình bộ chuyển đổi này trên toàn cầu:

  • enum nếu bạn muốn enum luôn được nối tiếp / giải tuần tự dưới dạng chuỗi:

    [JsonConverter(typeof(StringEnumConverter))]  
    enum Gender { Male, Female }
  • Trong trường hợp bất kỳ ai muốn tránh trang trí thuộc tính, bạn có thể thêm trình chuyển đổi vào JsonSerializer (được đề xuất bởi Bjørn Egil ):

    serializer.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter()); 

    và nó sẽ hoạt động cho mọi enum mà nó nhìn thấy trong quá trình tuần tự hóa đó (được đề xuất bởi Travis ).

  • hoặc JsonConverter (được đề xuất bởi chuối ):

    JsonConvert.SerializeObject(MyObject, 
        new Newtonsoft.Json.Converters.StringEnumConverter());

Ngoài ra, bạn có thể kiểm soát vỏ và liệu các số có còn được chấp nhận hay không bằng cách sử dụng hàm tạo StringEnumConverter (NamingStrargety, Boolean) .


9
Theo liên kết để mô tả cách sử dụng nó trong ứng dụng asp.net mvc james.newtonking.com/archive/2008/10/16/ mẹo
RredCat

2
Đây là liên kết đến chức năng đó: james.newtonking.com/projects/json/help/html/ mẹo
CAD bloke

61
Cấu hình httpConfiguration = GlobalConfiguration.Configuration; config.Formatters.JsonFormatter.SerializerSinstall.Formatted = Newtonsoft.Json.Formatted.Inent; config.Formatters.JsonFormatter.SerializerSinstall.Converters.Add (new Newtonsoft.Json.Converters.StringEnumConverter ());
Iggy

1
Theo mặc định, ASP.NET MVC rất hữu ích khi không sử dụng Json.Net làm trình tuần tự hóa json và người ta cần phải mở rộng Controllerhoặc ghi đè thủ công mỗi lần tuần tự hóa.
Odys

2
Bạn có thể tùy chỉnh trình chuyển đổi (giả sử, cho camelCaseđầu ra):new StringEnumConverter { CamelCaseText = true }
Cá biển

172

Thêm phần bên dưới vào global.asax của bạn để tuần tự hóa c # enum dưới dạng chuỗi

  HttpConfiguration config = GlobalConfiguration.Configuration;
            config.Formatters.JsonFormatter.SerializerSettings.Formatting =
                Newtonsoft.Json.Formatting.Indented;

            config.Formatters.JsonFormatter.SerializerSettings.Converters.Add
                (new Newtonsoft.Json.Converters.StringEnumConverter());

4
Vì một số lý do, tôi không làm việc này. Fiddler cho thấy một 2 cứng đầu hơn là 'Cảnh báo', ngay cả với điều này tại chỗ. Ngoài ra - bất kỳ lý do tại sao để thay đổi Formattingthành Indented?
sq33G

5
Dòng thứ ba từ ví dụ này đã được thêm vào tệp App_start / webapiconfig.cs và đã thực hiện một mẹo cho tôi trong dự án ASP.NET Web API 2.1 để trả về chuỗi cho các giá trị enum trong các lệnh gọi REST (json fomat).
Greg Z.

1
Có cách nào để chỉ đặt thuộc tính này cho mỗi Phạm vi yêu cầu không?
Anestis Kivranoglou

@AnestisKivranoglou chỉ cần sử dụng bộ nối tiếp json tùy chỉnh cho mỗi yêu cầu với cài đặt riêng của nó.
BrainSlugs83

3
cài đặt serializer đầu tiên của thụt lề không liên quan đến câu hỏi op.
dùng3791372

153

Câu trả lời @Iggy đặt tuần tự hóa JSON của c # enum dưới dạng chuỗi chỉ dành cho ASP.NET (API Web và v.v.).

Nhưng để làm cho nó hoạt động với tính năng tuần tự hóa ad hoc, hãy thêm theo dõi vào lớp bắt đầu của bạn (như 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;
});

Thêm thông tin trên trang Json.NET

Ngoài ra, để có thành viên enum của bạn nối tiếp / giải tuần tự đến / từ văn bản cụ thể, hãy sử dụng

System.R.78.Serialization.EnumMember

thuộc tính, như thế này:

public enum time_zone_enum
{
    [EnumMember(Value = "Europe/London")] 
    EuropeLondon,

    [EnumMember(Value = "US/Alaska")] 
    USAlaska
}

6
Cảm ơn bạn! Tôi chỉ tìm kiếm [EnumMember].
Poulad

Tài CamelCaseTextsản hiện được đánh dấu lỗi thời. Cách mới để khởi tạo trình chuyển đổi:new StringEnumConverter(new CamelCaseNamingStrategy())
fiat

Cảm ơn bạn rất nhiều, làm cho ngày của tôi! :)
Eldoïr

39

Tôi không thể thay đổi mô hình nguồn như trong câu trả lời hàng đầu (của @ob.) Và tôi không muốn đăng ký nó trên toàn cầu như @Iggy. Vì vậy, tôi đã kết hợp https://stackoverflow.com/a/2870420/237091 và @ Iggy https://stackoverflow.com/a/18152942/237091 để cho phép thiết lập trình chuyển đổi enum chuỗi trong chính lệnh 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()
        }
    })

điều này cũng thật tuyệt nếu bạn có một tài sản như Danh sách này <someEnumType>
Bogdan

34

Sự kết hợp giữa câu trả lời của Omer Bokhari và uri là giải pháp cho tôi vì các giá trị mà tôi muốn cung cấp thường khác với những gì tôi có trong enum đặc biệt là tôi muốn có thể thay đổi enum của mình nếu tôi cần.

Vì vậy, nếu bất cứ ai quan tâm, nó là một cái gì đó như thế này:

public enum Gender
{
   [EnumMember(Value = "male")] 
   Male,
   [EnumMember(Value = "female")] 
   Female
}

class Person
{
    int Age { get; set; }
    [JsonConverter(typeof(StringEnumConverter))]
    Gender Gender { get; set; }
}

1
Tôi đã sử dụng JsonPropertyAttributecho các thành viên enum và nó đang làm việc cho các nhiệm vụ giải trừ đơn giản. Đáng buồn thay, trong quá trình điều chỉnh thủ công với JTokens, nó bị bỏ qua. Happilly EnumMemberAttributehoạt động như một lá bùa. Cảm ơn!
Prolog

Điều đó làm việc với JavaScriptSerializer?
Stephen Kennedy

31

Đây có thể dễ dàng thực hiện bằng cách thêm một ScriptIgnorethuộc tính đến Genderbất động sản, làm cho nó không được tuần tự, và thêm một GenderStringtài sản mà không được đăng:

class Person
{
    int Age { get; set; }

    [ScriptIgnore]
    Gender Gender { get; set; }

    string GenderString { get { return Gender.ToString(); } }
}

29
Hãy để tôi cố gắng giải thích. Giải pháp này không đúng theo các nhà thiết kế. Bạn sửa đổi mô hình theo mục đích xem. Nhưng mô hình phải chỉ chứa dữ liệu và không quan tâm đến các bài thuyết trình. Bạn phải di chuyển chức năng này trên lớp khác.
RredCat

4
Trên thực tế, Model được sử dụng để truyền dữ liệu từ bộ điều khiển, vì nó là bộ điều khiển, người không quan tâm đến việc trình bày. Giới thiệu thuộc tính tự động (Giới tính tại đây) không phá vỡ bộ điều khiển, vẫn sử dụng thuộc tính Giới tính, nhưng cung cấp quyền truy cập dễ dàng để xem. Giải pháp logic.
Dima

17
@RredCat Không có gì sai khi có các thuộc tính dành riêng cho chế độ xem trong "mô hình xem". IMHO sai lầm sẽ không để phân chia các mô hình nhìn từ mô hình miền: blogs.msdn.com/b/simonince/archive/2010/01/26/...
Mariano Desanze

5
@RredCat, ngay cả khi nó không chính xác theo một số mẫu, OP không nói gì về điều này, vì vậy đây thực sự là một câu trả lời đúng. (Ngay cả khi tôi về mặt triết học có thể đồng ý với quan điểm của bạn.)
MEMark

10
Các xe đạp vô lý ngớ ngẩn trong chủ đề bình luận này là hấp dẫn.
Mike Mooney

26

Phiên bản câu trả lời này của Stephen không thay đổi tên trong 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; 
        }
    }
}

3
Tôi tin rằng điều này hợp lệ cho DataContractJsonSerializerkhôngJavaScriptSerializer
KCD

Đơn giản và giải quyết vấn đề cho tôi bằng cách sử dụng tuần tự hóa .NET framework.
Thượng nghị sĩ

Giải pháp tốt nhất cho tôi vì tôi không được phép sử dụng các thư viện của bên thứ 3 (các vấn đề về tuân thủ ISO)
Daniel Gruszchot

Tất nhiên, đây không phải là loại serialiser trong câu hỏi. JavaScriptSerializer tuần tự hóa mọi thứ không bị bỏ qua, trong khi DataContractJsonSerializer yêu cầu các thuộc tính DataMember. Cảm ơn vì đã hét to nhưng xin lưu ý rằng bạn đã đánh vần sai tên tôi :)
Stephen Kennedy

25

Đây là câu trả lời cho newtonsoft.json

enum Gender { Male, Female }

class Person
{
    int Age { get; set; }

    [JsonConverter(typeof(StringEnumConverter))]
    Gender Gender { get; set; }
}

1
Cảm ơn bạn vì câu trả lời này, đã giúp tôi rất nhiều! Nếu bạn muốn xác định enum của mình trong PascalCase, nhưng bạn muốn nó được tuần tự hóa trong camelCase thì bạn cần thêm truevào loại JsonConverter của mình như sau:[JsonConverter(typeof(StringEnumConverter), true)]
Peet


16

Bạn cũng có thể thêm trình chuyển đổi vào JsonSerializernếu bạn không muốn sử dụng JsonConverterthuộc tính:

string SerializedResponse = JsonConvert.SerializeObject(
     objToSerialize, 
     new Newtonsoft.Json.Converters.StringEnumConverter()
); 

Nó sẽ hoạt động cho mọi thứ enumnó nhìn thấy trong quá trình tuần tự hóa đó.


15

Đây là một giải pháp đơn giản để tuần tự hóa C # enum phía máy chủ thành JSON và sử dụng kết quả để đưa vào <select>phần tử phía máy khách . Điều này làm việc cho cả enums đơn giản và enum bitflag.

Tôi đã đưa vào giải pháp đầu cuối bởi vì tôi nghĩ rằng hầu hết mọi người muốn tuần tự hóa C # enum thành JSON cũng có thể sẽ sử dụng nó để điền vào phần <select>thả xuống.

Đây là:

Ví dụ Enum

public enum Role
{
    None = Permission.None,
    Guest = Permission.Browse,
    Reader = Permission.Browse| Permission.Help ,
    Manager = Permission.Browse | Permission.Help | Permission.Customise
}

Một enum phức tạp sử dụng OR bitwise để tạo ra một hệ thống quyền. Vì vậy, bạn không thể dựa vào chỉ mục đơn giản [0,1,2 ..] cho giá trị nguyên của enum.

Phía máy chủ - 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);
};

Đoạn mã trên sử dụng khung NancyFX để xử lý yêu cầu Nhận. Nó sử dụng Response.AsJson()phương thức trợ giúp của Nancy - nhưng đừng lo lắng, bạn có thể sử dụng bất kỳ trình định dạng JSON tiêu chuẩn nào vì enum đã được chiếu thành một loại ẩn danh đơn giản sẵn sàng để tuần tự hóa.

Đã tạo JSON

[
    {"Id":0,"Name":"None"},
    {"Id":2097155,"Name":"Guest"},
    {"Id":2916367,"Name":"Reader"},
    {"Id":4186095,"Name":"Manager"}
]

Phía khách hàng - 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 trước

<select id="role" name="role"></select>

HTML sau

<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>

13

Đối với lõi ASP.Net Chỉ cần thêm phần sau vào Lớp Khởi động của bạn:

JsonConvert.DefaultSettings = (() =>
        {
            var settings = new JsonSerializerSettings();
            settings.Converters.Add(new StringEnumConverter { AllowIntegerValues = false });
            return settings;
        });

1
Điều này hoạt động cho tất cả các phiên bản, không chỉ cốt lõi.
bikeman868

11

Bạn có thể tạo JsonSerializerS Settings bằng lệnh gọi đến JsonConverter.SerializeObject như sau:

var result = JsonConvert.SerializeObject
            (
                dataObject,
                new JsonSerializerSettings
                {
                    Converters = new [] {new StringEnumConverter()}
                }
            );

10

Lưu ý rằng không có câu trả lời cho việc tuần tự hóa khi có thuộc tính Mô tả.

Đây là triển khai của tôi hỗ trợ thuộc tính Mô tả.

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
}

Sử dụng:

[JsonConverter(typeof(CustomStringEnumConverter))]
public FooEnum test { get; set; }

10

Đối với .Net Core: -

public void ConfigureServices(IServiceCollection services)
{
    ...
    services.AddJsonFormatters(f => f.Converters.Add(new StringEnumConverter()));
    ...
}

2
Nếu đây là một trong Microsoft.AspNetCore.Mvc.Formatters.Jsongói NuGet, thì nó dường như chỉ là một phương thức mở rộng IMvcCoreBuilderchứ không phải IMvcBuilder. Vì vậy, nó được sử dụng như thế nào services.AddMvcCore().AddJsonFormatters(f => f.Converters.Add(new StringEnumConverter()));.
Infl3x

9

Trong .net core 3, điều này hiện có thể thực hiện được với các lớp tích hợp trong System.Text.Json:

var person = new Person();
// Create and add a converter which will use the string representation instead of the numeric value.
var stringEnumConverter = new System.Text.Json.Serialization.JsonStringEnumConverter();
JsonSerializerOptions opts = new JsonSerializerOptions();
opts.Converters.Add(stringEnumConverter);
// Generate json string.
var json = JsonSerializer.Serialize<Person>(person, opts);

Để cấu hình JsonStringEnumConvertervới trang trí thuộc tính cho thuộc tính cụ thể:

using System.Text.Json.Serialization;

[JsonConverter(typeof(JsonStringEnumConverter))]
public Gender Gender { get; set; }

Nếu bạn muốn luôn chuyển đổi enum dưới dạng chuỗi, hãy đặt thuộc tính tại chính enum.

[JsonConverter(typeof(JsonStringEnumConverter))] 
enum Gender { Male, Female }

9

Asp.Net Core 3 với System.Text.Json

public void ConfigureServices(IServiceCollection services)
{

    services
        .AddControllers()
        .AddJsonOptions(options => 
           options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter())
        );

    //...
 }

8

Chỉ trong trường hợp bất cứ ai thấy không đủ ở trên, tôi đã kết thúc với sự quá tải này:

JsonConvert.SerializeObject(objToSerialize, Formatting.Indented, new Newtonsoft.Json.Converters.StringEnumConverter())

Đây là một giải pháp tốt cho trường hợp sử dụng hiện tại của tôi: Tôi không muốn thay đổi mặc định của bộ xê-ri hóa và tôi gặp vấn đề khi sử dụng thuộc tính, vì các thuộc tính của tôi thuộc loại IList <EnumType>.
Dirk Brockhaus

5

Đây là một câu hỏi cũ nhưng tôi nghĩ tôi chỉ đóng góp trong trường hợp. Trong các dự án của tôi, tôi sử dụng các mô hình riêng biệt cho bất kỳ yêu cầu Json nào. Một mô hình thường có cùng tên với đối tượng miền với tiền tố "Json". Các mô hình được ánh xạ bằng AutoMapper . Bằng cách mô hình json khai báo một thuộc tính chuỗi là enum trên lớp miền, AutoMapper sẽ giải quyết trình bày chuỗi của nó.

Trong trường hợp bạn đang tự hỏi, tôi cần các mô hình riêng biệt cho các lớp được tuần tự hóa Json bởi vì serializer inbuilt đi kèm với các tham chiếu vòng tròn khác.

Hy vọng điều này sẽ giúp được ai đó.


Rất vui được biết tính năng đó của thuộc tính Automapper ;-) [ScriptIgnore] sẽ xóa tham chiếu vòng tròn
ledragon 27/03/13

1
Oh. Không biết về thuộc tính. Cảm ơn! Bạn sẽ sử dụng nó trên Pocos của bạn? Tôi đã sử dụng các định nghĩa MetadataType cho bất kỳ thuộc tính Poco nào chỉ để giữ cho chúng sạch sẽ. Thuộc tính vẫn hoạt động thông qua dữ liệu meta?
Ales Potocnik Hahonina

3

Bạn thực sự có thể sử dụng JavaScriptConverter để thực hiện việc này với JavaScriptSerializer tích hợp. Bằng cách chuyển đổi enum của bạn thành Uri, bạn có thể mã hóa nó thành một chuỗi.

Tôi đã mô tả làm thế nào để làm điều này cho ngày nhưng nó cũng có thể được sử dụng cho enums. Định dạng JSON tùy chỉnh DateTime cho .NET JavaScriptSerializer .


Giải pháp rất thú vị! Cám ơn vì đã chia sẻ.
Oliver

1

Không chắc điều này có còn liên quan hay không nhưng tôi đã phải viết thẳng vào một tệp json và tôi đã đưa ra một số câu trả lời stackoverflow sau đây cùng nhau

public class LowercaseJsonSerializer
{
    private static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
    {
        ContractResolver = new LowercaseContractResolver()
    };

    public static void Serialize(TextWriter file, object o)
    {
        JsonSerializer serializer = new JsonSerializer()
        {
            ContractResolver = new LowercaseContractResolver(),
            Formatting = Formatting.Indented,
            NullValueHandling = NullValueHandling.Ignore
        };
        serializer.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());
        serializer.Serialize(file, o);
    }

    public class LowercaseContractResolver : DefaultContractResolver
    {
        protected override string ResolvePropertyName(string propertyName)
        {
            return Char.ToLowerInvariant(propertyName[0]) + propertyName.Substring(1);
        }
    }
}

Nó đảm bảo tất cả các khóa json của tôi là chữ thường bắt đầu theo "quy tắc" của json. Định dạng nó rõ ràng thụt lề và bỏ qua null trong đầu ra. Aslo bằng cách thêm StringEnumConverter, nó sẽ in các enum với giá trị chuỗi của chúng.

Cá nhân tôi thấy đây là thứ sạch nhất tôi có thể nghĩ ra, mà không phải làm bẩn mô hình bằng các chú thích.

sử dụng:

    internal void SaveJson(string fileName)
    {
        // serialize JSON directly to a file
        using (StreamWriter file = File.CreateText(@fileName))
        {
            LowercaseJsonSerializer.Serialize(file, jsonobject);
        }
    }

0

Tôi đã tập hợp tất cả các phần của giải pháp này bằng Newtonsoft.Jsonthư viện. Nó sửa lỗi enum và cũng giúp xử lý lỗi tốt hơn nhiều và nó hoạt động trong các dịch vụ lưu trữ IIS. Đó là khá nhiều mã, vì vậy bạn có thể tìm thấy nó trên GitHub tại đây: https://github.com/jongrant/wcfjsonserializer/blob/master/NewtonsoftJsonFormatter.cs

Bạn phải thêm một số mục vào để làm Web.configcho nó hoạt động, bạn có thể xem tệp ví dụ tại đây: https://github.com/jongrant/wcfjsonserializer/blob/master/Web.config


0

Và đối với VB.net tôi đã tìm thấy các tác phẩm sau:

Dim sec = New Newtonsoft.Json.Converters.StringEnumConverter()
sec.NamingStrategy() = New Serialization.CamelCaseNamingStrategy

Dim JSON_s As New JsonSerializer
JSON_s.Converters.Add(sec)

Dim jsonObject As JObject
jsonObject = JObject.FromObject(SomeObject, JSON_s)
Dim text = jsonObject.ToString

IO.File.WriteAllText(filePath, text)

0

Một lựa chọn tương lai hơn một chút

Đối mặt với cùng một câu hỏi, chúng tôi xác định rằng chúng tôi cần một phiên bản tùy chỉnh StringEnumConverterđể đảm bảo rằng các giá trị enum của chúng tôi có thể mở rộng theo thời gian mà không phá vỡ thảm khốc ở phía khử lưu huỳnh (xem nền bên dưới). Việc sử dụng SafeEnumConverterbên dưới cho phép quá trình khử lưu huỳnh kết thúc ngay cả khi tải trọng chứa giá trị cho enum không có định nghĩa được đặt tên, gần hơn với cách chuyển đổi int-to-enum sẽ hoạt động.

Sử dụng:

[SafeEnumConverter]
public enum Colors
{
    Red,
    Green,
    Blue,
    Unsupported = -1
}

hoặc là

[SafeEnumConverter((int) Colors.Blue)]
public enum Colors
{
    Red,
    Green,
    Blue
}

Nguồn:

public class SafeEnumConverter : StringEnumConverter
{
    private readonly int _defaultValue;

    public SafeEnumConverter()
    {
        // if you've been careful to *always* create enums with `0` reserved
        // as an unknown/default value (which you should), you could use 0 here. 
        _defaultValue = -1;
    }

    public SafeEnumConverter(int defaultValue)
    {
        _defaultValue = defaultValue;
    }

    /// <summary>
    /// Reads the provided JSON and attempts to convert using StringEnumConverter. If that fails set the value to the default value.
    /// </summary>
    /// <returns>The deserialized value of the enum if it exists or the default value if it does not.</returns>
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        try
        {
            return base.ReadJson(reader, objectType, existingValue, serializer);
        }
        catch
        {
            return Enum.Parse(objectType, $"{_defaultValue}");
        }
    }

    public override bool CanConvert(Type objectType)
    {
        return base.CanConvert(objectType) && objectType.GetTypeInfo().IsEnum;
    }
}

Lý lịch

Khi chúng tôi xem xét việc sử dụng StringEnumConverter, vấn đề chúng tôi gặp phải là chúng tôi cũng cần sự thụ động cho các trường hợp khi giá trị enum mới được thêm vào, nhưng không phải mọi khách hàng đều biết ngay về giá trị mới. Trong các trường hợp này, StringEnumConvertergói Newtonsoft Newton đóng gói JsonSerializationExceptiontương tự như "Lỗi chuyển đổi giá trị someString sang loại EnumType" và sau đó toàn bộ quá trình khử lưu huỳnh không thành công. Đây là một công cụ thỏa thuận đối với chúng tôi, bởi vì ngay cả khi khách hàng lên kế hoạch bỏ qua / loại bỏ giá trị tài sản mà họ không hiểu, thì vẫn cần phải có khả năng giải trừ phần còn lại của tải trọng!


-2
        Person p = new Person();
        p.Age = 35;
        p.Gender = Gender.Male;
        //1.  male="Male";
        string male = Gender.Male.ToString();

        p.Gender = Gender.Female;

        //2.  female="Female";
        string female = Enum.GetName(typeof(Gender), p.Gender);

        JObject jobj = new JObject();
        jobj["Age"] = p.Age;
        jobj["Gender"] = male;
        jobj["Gender2"] = female;

        //you result:  josn= {"Age": 35,"Gender": "Male","Gender2": "Female"}
        string json = jobj.ToString();

-5
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]  
);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.