[英]How to convert camel case to snake case with two capitals next to each other
[英]Convert JSON camel case to snake case (and vice versa) and stringify numeric values
我必須向 Web REST 服務發送和接收 JSON 對象。 這些對象由一個 DLL 生成,該 DLL 將大寫字母(“PropertyName”)中的屬性名稱序列化,並且 Web 服務需要蛇形大小寫(“property_name”)。 另外,DLL 將數值序列化為浮點數,但 REST API 需要所有字符串。 處理對象后,REST 服務返回蛇形大小寫 JSON。
JSON 很復雜並且包含嵌套的數組和對象。 在從 REST 字符串轉換回來時,我可以跳過數字字符串的去字符串化,但我仍然必須將屬性名稱重新轉換為大寫字母。
我正在考慮使用 Newtonsoft Json 庫編寫一個輔助類,但它看起來比我預期的要棘手。 轉換器應接受 JSON 並返回 JSON。
例子:
{
"FirstObject": {
"NestedObject": {
"AttributeString": "ok",
"AttributeNumeric": 123.45
},
"OtherObject": [{
"ArrayVal": 100
}, {
"ArrayVal": 200
}]
}
}
應該成為
{
"first_object": {
"nested_object": {
"attribute_string": "ok",
"attribute_numeric": "123.45"
},
"other_object": [{
"array_val": "100"
}, {
"array_val": "200"
}]
}
}
我看到 Json.Net 庫有SnakeCaseNamingStrategy
和CamelCaseNamingStrategy
類,所以想法是使用JsonTextReader
來解析輸入,更改屬性名稱的命名約定,將數值設置為字符串,並使用JsonTextWriter
編寫修改后的標記。
我找不到有關如何執行此操作的任何示例。
做你想做的最簡單的方法是使用一組與你的 JSON 匹配的模型類。 (您可以通過將 JSON 的完整示例復制到剪貼板,然后使用Edit -> Paste Special -> Paste JSON as Classes
函數在 Visual Studio 中生成Edit -> Paste Special -> Paste JSON as Classes
。)使模型類對屬性名稱使用大寫駝峰(無論如何,這是 C# 的標准命名約定),並使用字符串代替數字屬性。
因此,對於您的示例 JSON,模型類將如下所示:
public class RootObject
{
public FirstObject FirstObject { get; set; }
}
public class FirstObject
{
public NestedObject NestedObject { get; set; }
public List<OtherObject> OtherObject { get; set; }
}
public class NestedObject
{
public string AttributeString { get; set; }
public string AttributeNumeric { get; set; }
}
public class OtherObject
{
public string ArrayVal { get; set; } // using string instead of int here
}
然后,要將駝峰式大寫 JSON 轉換為蛇式大寫,您可以執行以下操作:
var obj = JsonConvert.DeserializeObject<RootObject>(json);
var settings = new JsonSerializerSettings
{
ContractResolver = new DefaultContractResolver
{
NamingStrategy = new SnakeCaseNamingStrategy { ProcessDictionaryKeys = true }
},
Formatting = Formatting.Indented
};
json = JsonConvert.SerializeObject(obj, settings);
原始 JSON 將自然地反序列化為模型,因為屬性名稱已經匹配。 Json.Net 將根據需要自動將 JSON 中的數值轉換為字符串以適合類屬性。 在序列化時, SnakeCaseNamingStrategy
開始發揮作用,將屬性名稱更改為蛇形大小寫。 數值作為字符串寫出,因為這是在類中聲明屬性的方式。
要以另一種方式返回,您將執行以下操作:
obj = JsonConvert.DeserializeObject<RootObject>(json, settings); // same settings as above
json = JsonConvert.SerializeObject(obj, Formatting.Indented);
在這里,在反序列化期間,Json.Net 使用SnakeCaseNamingStrategy
將模型屬性名稱再次轉換為蛇形大小寫,以將它們與 JSON 屬性匹配。 數值已經是 JSON 中的字符串,因此不需要轉換。 在序列化時,我們不使用任何特殊設置,因此屬性名稱完全按照聲明的方式寫出,這是大寫的駝峰式。 保存數值的字符串屬性仍然是字符串(您在問題中說這沒問題)。
這是一個往返演示: https : //dotnetfiddle.net/3Pb1fT
如果您沒有可以使用的模型,仍然可以使用您建議的JsonReader
/ JsonWriter
方法進行此轉換,但是將它們粘合在一起並進行轉換需要更多代碼。 這是一個輔助方法,可以完成大部分繁重的工作:
public static void ConvertJson(TextReader textReader, TextWriter textWriter,
NamingStrategy strategy,
Formatting formatting = Formatting.Indented)
{
using (JsonReader reader = new JsonTextReader(textReader))
using (JsonWriter writer = new JsonTextWriter(textWriter))
{
writer.Formatting = formatting;
if (reader.TokenType == JsonToken.None)
{
reader.Read();
ConvertJsonValue(reader, writer, strategy);
}
}
}
private static void ConvertJsonValue(JsonReader reader, JsonWriter writer,
NamingStrategy strategy)
{
if (reader.TokenType == JsonToken.StartObject)
{
writer.WriteStartObject();
while (reader.Read() && reader.TokenType != JsonToken.EndObject)
{
string name = strategy.GetPropertyName((string)reader.Value, false);
writer.WritePropertyName(name);
reader.Read();
ConvertJsonValue(reader, writer, strategy);
}
writer.WriteEndObject();
}
else if (reader.TokenType == JsonToken.StartArray)
{
writer.WriteStartArray();
while (reader.Read() && reader.TokenType != JsonToken.EndArray)
{
ConvertJsonValue(reader, writer, strategy);
}
writer.WriteEndArray();
}
else if (reader.TokenType == JsonToken.Integer)
{
// convert integer values to string
writer.WriteValue(Convert.ToString((long)reader.Value));
}
else if (reader.TokenType == JsonToken.Float)
{
// convert floating point values to string
writer.WriteValue(Convert.ToString((double)reader.Value,
System.Globalization.CultureInfo.InvariantCulture));
}
else // string, bool, date, etc.
{
writer.WriteValue(reader.Value);
}
}
要使用它,您只需要為您的輸入 JSON 設置一個TextReader
為輸出設置一個TextWriter
,並傳入您想要用於轉換的適當NamingStrategy
。 例如,要將原始 JSON 字符串轉換為蛇形大小寫,您可以這樣做:
using (StringReader sr = new StringReader(upperCamelCaseJson))
using (StringWriter sw = new StringWriter())
{
ConvertJson(sr, sw, new SnakeCaseNamingStrategy(), formatting);
string snakeCaseJson = sw.ToString();
...
}
或者,如果 JSON 的源和/或目標是某種流,則可以改用StreamReader
/ StreamWriter
:
using (StreamReader sr = new StreamReader(inputStream))
using (StreamWriter sw = new StreamWriter(outputStream))
{
ConvertJson(sr, sw, new SnakeCaseNamingStrategy(), formatting);
}
現在,對於回程,有一點問題。 NamingStrategy
只在一個方向上起作用; 它不提供反轉轉換的工具。 這意味着 Newtonsoft 提供的所有NamingStrategy
類都無法按照您想要的方式將蛇形大小寫轉換回駝色大寫字母。 CamelCaseNamingStrategy
將不起作用,因為它不希望以蛇形字母開頭(它想要大駝峰字母),而且它的輸出無論如何都不是大駝峰字母。 DefaultNamingStrategy
也不會工作,因為它實際上根本不做任何轉換——它只是一個傳遞。
解決方案是制作您自己的自定義NamingStrategy
。 幸運的是,這並不難做到。 只需從基礎NamingStrategy
類派生並實現抽象ResolvePropertyName
方法:
// This naming strategy converts snake case names to upper camel case (a.k.a. proper case)
public class ProperCaseFromSnakeCaseNamingStrategy : NamingStrategy
{
protected override string ResolvePropertyName(string name)
{
StringBuilder sb = new StringBuilder(name.Length);
for (int i = 0; i < name.Length; i++)
{
char c = name[i];
if (i == 0 || name[i - 1] == '_')
c = char.ToUpper(c);
if (c != '_')
sb.Append(c);
}
return sb.ToString();
}
}
現在,您可以將這個新策略傳遞給上述ConvertJson
方法,以將蛇形大小寫 JSON 轉換回駝峰大寫。
往返演示: https : //dotnetfiddle.net/jt0XKD
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.