Đảm bảo các khóa json là chữ thường trong .NET


103

Có cách đơn giản nào sử dụng JSON trong .NET để đảm bảo rằng các khóa được gửi dưới dạng chữ thường không?

Hiện tại, tôi đang sử dụng thư viện Json.NET của newtonsoft và chỉ đơn giản là sử dụng

string loginRequest = JsonConvert.SerializeObject(auth);

Trong trường hợp authnày chỉ là đối tượng sau

public class Authority
{
    public string Username { get; set; }
    public string ApiToken { get; set; }
}

Kết quả này trong

{"Username":"Mark","ApiToken":"xyzABC1234"}

Có cách nào để đảm bảo rằng các phím usernameapitokenphím đi qua là chữ thường không?

Tất nhiên, tôi không muốn chỉ đơn giản chạy nó String.ToLower()vì các giá trị cho usernameapitokenlà trường hợp hỗn hợp.

Tôi nhận ra rằng tôi có thể lập trình làm điều này và tạo chuỗi JSON theo cách thủ công, nhưng tôi cần điều này cho khoảng 20 chuỗi dữ liệu JSON hoặc hơn và tôi đang xem liệu tôi có thể tiết kiệm thời gian cho mình hay không. Tôi tự hỏi liệu có thư viện nào đã được xây dựng sẵn cho phép bạn thực thi chữ thường để tạo khóa hay không.


Có thể lib tuần tự hóa json cung cấp một số loại thuộc tính tuần tự hóa mà bạn có thể sử dụng để thay đổi tên tuần tự hóa json cho các thuộc tính của mình?
tdammers

@tdammers, cảm ơn Tôi đang cố gắng tìm thứ gì đó làm được điều đó, nhưng không thành công cho đến nay. Hy vọng ai đó ở đây có thể chỉ cho tôi nó.
Đánh dấu

1
Điều này có thể hữu ích trong trường hợp bạn có một từ.
Lipotam

Huh. Tôi đang gặp vấn đề ngược lại ... ngoài ra - thật buồn cười khi bạn đề cập đến "Tên người dùng" là trường hợp hỗn hợp. Ý của bạn là "Tên người dùng"?
BrainSlugs83

Không chỉ đơn giản là các giá trị cần thiết để duy trì trường hợp hỗn hợp, các phím Chỉ là những gì tôi cần chạm vào. Giá trị để lại một mình.
Đánh dấu

Câu trả lời:


176

Bạn có thể tạo một trình giải quyết hợp đồng tùy chỉnh cho việc này. Trình giải quyết hợp đồng sau sẽ chuyển đổi tất cả các khóa thành chữ thường:

public class LowercaseContractResolver : DefaultContractResolver
{
    protected override string ResolvePropertyName(string propertyName)
    {
        return propertyName.ToLower();
    }
}

Sử dụng:

var settings = new JsonSerializerSettings();
settings.ContractResolver = new LowercaseContractResolver();
var json = JsonConvert.SerializeObject(authority, Formatting.Indented, settings);

Wil kết quả là:

{"username":"Mark","apitoken":"xyzABC1234"}

Nếu bạn luôn muốn tuần tự hóa bằng cách sử dụng LowercaseContractResolver, hãy xem xét gói nó trong một lớp để tránh lặp lại chính mình:

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

    public static string SerializeObject(object o)
    {
        return JsonConvert.SerializeObject(o, Formatting.Indented, Settings);
    }

    public class LowercaseContractResolver : DefaultContractResolver
    {
        protected override string ResolvePropertyName(string propertyName)
        {
            return propertyName.ToLower();
        }
    }
}

Có thể được sử dụng như thế này:

var json = LowercaseJsonSerializer.SerializeObject(new { Foo = "bar" });
// { "foo": "bar" }

ASP.NET MVC4 / WebAPI

Nếu bạn đang sử dụng ASP.NET MVC4 / WebAPI, bạn có thể sử dụng CamelCasePropertyNamesContractResolverthư viện từ Newtonsoft.Json được bao gồm theo mặc định.


bất kỳ cách hợp lý để làm điều này ngược lại? Đối với deserialization?
Shaun Rowan

1
@Anzeo Tôi chưa cố gắng tự làm điều đó và tôi không tìm thấy bất kỳ thông tin nào về điều đó trong tài liệu. Một giải pháp sẽ là bọc JsonConvert.SerializeObject trong lớp của riêng bạn. Xem bản cập nhật của tôi.
alexn

3
Có vẻ như, bộ giải pháp hợp đồng tùy chỉnh này không tính đến thuộc tính JsonProperty, nếu bạn muốn chỉ định ngoại lệ ... ví dụ: [JsonProperty ("alternateName")] vẫn được viết thường hoặc có cách nào khác để làm điều đó?
rekna 29/09/12

2
+1 để chỉ ra CamelCasePropertyNamesContractResolver. Bây giờ tôi thấy System.Net.Http.Formatting.JsonContractResolverlà mặc định trong WebAPI và lớp này là nội bộ. Tôi kết thúc với việc viết lại JsonContractResolverbằng hộp đựng lạc đà. Ai đó đã báo cáo điều này là công khai aspnetwebstack.codeplex.com/workitem/228
CallMeLaNN

10
CamelCasePropertyNamesContratResolverkhông biến đổi các thuộc tính ở dạng chữ thường, chỉ là ký tự đầu tiên.
ToXinE

23
protected void Application_Start() {
    JsonConfig.Configure();   
}

public static class JsonConfig
{
    public static void Configure(){
        var formatters = GlobalConfiguration.Configuration.Formatters;
        var jsonFormatter = formatters.JsonFormatter;
        var settings = jsonFormatter.SerializerSettings;

        settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
    }
}

10

Trong Json.NET 9.0.1 và mới hơn, có thể đảm bảo rằng tất cả các tên thuộc tính được chuyển đổi thành chữ thường bằng cách sử dụng một tùy chỉnh NamingStrategy. Lớp này trích xuất logic để ánh xạ lại theo thuật toán của các tên thuộc tính từ trình phân giải hợp đồng thành một đối tượng riêng biệt, nhẹ có thể được đặt trên đó DefaultContractResolver.NamingStrategy. Làm như vậy tránh được sự cần thiết phải tạo ra một tùy chỉnhContractResolver và do đó có thể dễ dàng tích hợp vào các khuôn khổ đã có trình giải quyết hợp đồng của riêng chúng.

Xác định LowercaseNamingStrategynhư sau:

public class LowercaseNamingStrategy : NamingStrategy
{
    protected override string ResolvePropertyName(string name)
    {
        return name.ToLowerInvariant();
    }
}

Sau đó tuần tự hóa như sau:

var settings = new JsonSerializerSettings
{
    ContractResolver = new DefaultContractResolver { NamingStrategy = new LowercaseNamingStrategy() },
};
string loginRequest = JsonConvert.SerializeObject(auth, settings);

Ghi chú -


8

bạn có thể sử dụng "JsonProperty":

Sử dụng:

public class Authority
{
    [JsonProperty("userName")] // or [JsonProperty("username")]
    public string Username { get; set; }
    [JsonProperty("apiToken")] // or [JsonProperty("apitoken")]
    public string ApiToken { get; set; }
}

var json  = JsonConvert.SerializeObject(authority);

0

Đối với tôi, tôi đã sử dụng kết hợp một số câu trả lời khác và kết quả là

        return JsonConvert.SerializeObject(obj, Formatting.Indented, new JsonSerializerSettings
        {
            ContractResolver = new CamelCasePropertyNamesContractResolver()
        });

gần hơn với một giải pháp cho những gì tôi đang tìm kiếm vì tôi không tìm cách tạo ra

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.