การตรวจสอบว่าคีย์ json เป็นตัวพิมพ์เล็กใน. NET


103

มีวิธีง่ายๆในการใช้ JSON ใน. NET เพื่อให้แน่ใจว่าคีย์ถูกส่งเป็นตัวพิมพ์เล็กหรือไม่?

ในขณะนี้ฉันใช้ไลบรารี Json.NET ของ newtonsoft และใช้งานไฟล์

string loginRequest = JsonConvert.SerializeObject(auth);

ในกรณีนี้authเป็นเพียงวัตถุต่อไปนี้

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

ซึ่งส่งผลให้

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

มีวิธีตรวจสอบให้แน่ใจว่าusernameและapitokenคีย์มาเป็นตัวพิมพ์เล็กหรือไม่?

ฉันไม่ต้องการเรียกใช้มันString.ToLower()แน่นอนเพราะค่าสำหรับusernameและapitokenเป็นกรณีผสม

ฉันรู้ว่าฉันสามารถทำสิ่งนี้โดยใช้โปรแกรมและสร้างสตริง JSON ด้วยตนเองได้ แต่ฉันต้องการสิ่งนี้สำหรับสตริงข้อมูล JSON ประมาณ 20 สตริงและฉันกำลังดูว่าจะประหยัดเวลาได้หรือไม่ ฉันสงสัยว่ามีไลบรารีที่สร้างไว้แล้วที่อนุญาตให้คุณบังคับใช้ตัวพิมพ์เล็กสำหรับการสร้างคีย์หรือไม่


บางที json serialization lib มีแอตทริบิวต์ serialization บางประเภทที่คุณสามารถใช้เพื่อเปลี่ยนชื่อ json-serialized ของคุณสมบัติของคุณได้หรือไม่?
tdammers

@tdammers ขอบคุณฉันพยายามหาบางอย่างที่ทำเช่นนั้น แต่ก็ไม่ประสบความสำเร็จ หวังว่าใครบางคนที่นี่จะชี้ให้ฉันเห็น
มาร์ค

1
สิ่งนี้จะมีประโยชน์ในกรณีที่คุณมีความเหมาะสมประกอบด้วยคำเดียว
Lipotam

ฮะ. ฉันมีปัญหาตรงข้าม ... เช่นกัน - เป็นเรื่องตลกที่คุณพูดถึง "ชื่อผู้ใช้" เป็นตัวพิมพ์เล็ก คุณหมายถึง "UserName" หรือเปล่า
BrainSlugs83

ไม่เพียงแค่ค่าที่จำเป็นในการใช้ตัวพิมพ์เล็กและใหญ่เท่านั้นคือสิ่งที่ฉันต้องสัมผัส ทิ้งคุณค่าไว้คนเดียว
Mark

คำตอบ:


176

คุณสามารถสร้างตัวแก้ไขสัญญาที่กำหนดเองสำหรับสิ่งนี้ ตัวแก้ไขสัญญาต่อไปนี้จะแปลงคีย์ทั้งหมดเป็นตัวพิมพ์เล็ก:

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

การใช้งาน:

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

Wil ส่งผลให้:

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

หากคุณต้องการทำให้เป็นอนุกรมโดยใช้สิ่งLowercaseContractResolverนี้เสมอให้พิจารณาห่อในชั้นเรียนเพื่อหลีกเลี่ยงการทำซ้ำ:

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();
        }
    }
}

ซึ่งสามารถใช้ได้ดังนี้:

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

ASP.NET MVC4 / WebAPI

หากคุณใช้ ASP.NET MVC4 / WebAPI คุณสามารถใช้CamelCasePropertyNamesContractResolverไลบรารีจาก Newtonsoft.Json ซึ่งรวมไว้โดยค่าเริ่มต้น


วิธีใดที่สมเหตุสมผลในการทำสิ่งนี้ในทางกลับกัน? สำหรับ deserialization?
Shaun Rowan

1
@ Anzeo ฉันไม่ได้พยายามทำด้วยตัวเองและฉันไม่พบข้อมูลใด ๆ เกี่ยวกับเรื่องนี้ในเอกสาร วิธีแก้ปัญหาคือการห่อ JsonConvert.SerializeObject ในคลาสของคุณเอง ดูการอัปเดตของฉัน
alexn

3
ดูเหมือนว่า contractresolver ที่กำหนดเองนี้ไม่ได้คำนึงถึงแอตทริบิวต์ JsonProperty หากคุณต้องการระบุข้อยกเว้น ... เช่น [JsonProperty ("alternateName")] ยังคงได้รับการลดขนาดลงหรือมีวิธีอื่นในการทำหรือไม่
rekna

2
+1 เพื่อชี้ให้เห็นCamelCasePropertyNamesContractResolver. ตอนนี้ฉันพบว่าSystem.Net.Http.Formatting.JsonContractResolverเป็นค่าเริ่มต้นใน WebAPI และคลาสนี้เป็นแบบภายใน ฉันจบลงด้วยการเขียนซ้ำด้วยJsonContractResolverเคสอูฐ มีคนรายงานว่านี่เป็นสาธารณะaspnetwebstack.codeplex.com/workitem/228
CallMeLaNN

10
CamelCasePropertyNamesContratResolverอย่าแปลงคุณสมบัติเป็นตัวพิมพ์เล็กเพียงแค่อักขระตัวแรก
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

ในJson.NET 9.0.1NamingStrategyและต่อมาก็เป็นไปได้เพื่อให้แน่ใจว่าชื่อสถานที่ทั้งหมดจะถูกแปลงเป็นตัวพิมพ์เล็กโดยใช้กำหนดเอง คลาสนี้แยกตรรกะสำหรับการแมปชื่อคุณสมบัติอัลกอริทึมจากตัวแก้ไขสัญญาไปยังอ็อบเจ็กต์น้ำหนักเบาที่แยกจากกันซึ่งสามารถตั้งค่าDefaultContractResolver.NamingStrategyได้ การทำเช่นนี้ช่วยหลีกเลี่ยงความจำเป็นในการสร้างแบบกำหนดเองContractResolverและอาจรวมเข้ากับเฟรมเวิร์กที่มีตัวแก้ไขสัญญาของตนเองได้ง่ายกว่า

กำหนดLowercaseNamingStrategyดังต่อไปนี้:

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

จากนั้นจัดลำดับดังนี้:

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

หมายเหตุ -

  • การใช้string.ToLowerInvariant()ทำให้แน่ใจว่ามีการสร้างสัญญาเดียวกันในทุกภาษา

  • เพื่อควบคุมว่าชื่อคุณสมบัติแทนที่คีย์พจนานุกรมและชื่อข้อมูลส่วนขยายกำลัง lowercased คุณสามารถตั้งค่าNamingStrategy.OverrideSpecifiedNames, NamingStrategy.ProcessDictionaryKeysหรือNamingStrategy.ProcessExtensionDataNames(Json.NET 10.0.1 และต่อมา) trueเพื่อ

  • คุณอาจต้องการแคชจำแนกสัญญาเพื่อประสิทธิภาพที่ดีที่สุด

  • หากคุณไม่สามารถเข้าถึงการตั้งค่าซีเรียลไลเซอร์ในเฟรมเวิร์กของคุณคุณสามารถใช้ a NamingStrategyโดยตรงกับวัตถุของคุณได้ดังนี้:

    [JsonObject(NamingStrategyType = typeof(LowercaseNamingStrategy))]
    public class Authority
    {
        public string Username { get; set; }
        public string ApiToken { get; set; }
    }
  • อย่าแก้ไขNamingStrategyของCamelCasePropertyNamesContractResolver. ตัวแก้ไขสัญญานี้แชร์ข้อมูลประเภททั่วโลกในทุกอินสแตนซ์ดังนั้นการปรับเปลี่ยนอินสแตนซ์ใดก็ตามอาจมีผลข้างเคียงที่ไม่คาดคิด


8

คุณสามารถใช้ "JsonProperty":

การใช้งาน:

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

สำหรับฉันฉันใช้คำตอบอื่น ๆ รวมกันและลงเอยด้วยสิ่งนี้

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

อยู่ใกล้วิธีแก้ปัญหาสำหรับสิ่งที่ฉันกำลังมองหามากขึ้นเพราะฉันไม่ได้ต้องการสร้างของตัวเอง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.