使用Json.NET进行序列化时,如何应用重新映射所有属性名称的通用规则? [英] How to apply a general rule for remapping all property names when serializing with Json.NET?
问题描述
将Json对象反序列化为.Net type
时,如果字段名称不匹配,我发现您可以用[JsonProperty(PropertyName = "name")]
装饰type
的属性
When deserializing a Json object into a .Net type
, if the field names don't match up I found you can decorate your type
's properties with [JsonProperty(PropertyName = "name")]
对于一些不匹配的属性,这很好而且很花哨,但是有没有办法设置约定或规则?
This is fine and dandy for a couple of properties that don't match up, but is there a way to set a convention or rule?
Json
{
"Job": [
{
"Job #": "1",
"Job Type": "A",
}
]
}
C#
[JsonProperty(PropertyName = "Job Type")]
public string JobType { get; set; }
[JsonProperty(PropertyName = "Job #")]
public string JobNumber { get; set; }
我想弄清楚许多字段使用相似的名称,有没有办法告诉您设置规则以始终删除空格(例如,EG:Job Type -> JobType
)并将#
替换为Number
(例如:Job # -> JobNumber
)?
I have many fields using similar names, what I would like to figure out, is there a way to tell to set a rule to always remove spaces (EG: Job Type -> JobType
) and replace #
with Number
(eg: Job # -> JobNumber
)?
看来,自定义ContractResolver
可能是唯一的解决方案,但我似乎无法弄清楚如何使用它来拔出空格并将#"替换为"Number".有人有参考示例吗?
It looks like a custom ContractResolver
might be the only solution, but I can't seem to figure out how to go about using it to pluck out spaces and replace "#" with "Number". Does anyone have a reference example?
或者,我希望有一个很好的简单解决方案被我忽略了.
Or, I'm hoping there's a nice simple solution that I've overlooked.
P.S.也接受建议以获得更好的标题.
P.S. Also accepting suggestions for a better title.
推荐答案
假设您正在使用Json.NET NamingStrategy
.例如,这是一个基于 SnakeCaseNamingStrategy
和 StringUtils.ToSnakeCase()
:
Assuming you are working with Json.NET 9.0.1 or later, this can be done with a custom NamingStrategy
. For instance, here's one based on SnakeCaseNamingStrategy
and StringUtils.ToSnakeCase()
by James Newton-King:
public class CustomNamingStrategy : NamingStrategy
{
public CustomNamingStrategy(bool processDictionaryKeys, bool overrideSpecifiedNames)
{
ProcessDictionaryKeys = processDictionaryKeys;
OverrideSpecifiedNames = overrideSpecifiedNames;
}
public CustomNamingStrategy(bool processDictionaryKeys, bool overrideSpecifiedNames, bool processExtensionDataNames)
: this(processDictionaryKeys, overrideSpecifiedNames)
{
ProcessExtensionDataNames = processExtensionDataNames;
}
public CustomNamingStrategy()
{
}
protected override string ResolvePropertyName(string name)
{
return SpaceWords(name);
}
enum WordState
{
Start,
Lower,
Upper,
NewWord
}
static string SpaceWords(string s)
{
// Adapted from StringUtils.ToSnakeCase()
// https://github.com/JamesNK/Newtonsoft.Json/blob/master/Src/Newtonsoft.Json/Utilities/StringUtils.cs#L191
//
// Copyright (c) 2007 James Newton-King
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
char wordBreakChar = ' ';
if (string.IsNullOrEmpty(s))
{
return s;
}
StringBuilder sb = new StringBuilder();
WordState state = WordState.Start;
for (int i = 0; i < s.Length; i++)
{
if (s[i] == ' ')
{
if (state != WordState.Start)
{
state = WordState.NewWord;
}
}
else if (char.IsUpper(s[i]))
{
switch (state)
{
case WordState.Upper:
bool hasNext = (i + 1 < s.Length);
if (i > 0 && hasNext)
{
char nextChar = s[i + 1];
if (!char.IsUpper(nextChar) && nextChar != ' ')
{
sb.Append(wordBreakChar);
}
}
break;
case WordState.Lower:
case WordState.NewWord:
sb.Append(wordBreakChar);
break;
}
sb.Append(s[i]);
state = WordState.Upper;
}
else if (s[i] == wordBreakChar)
{
sb.Append(wordBreakChar);
state = WordState.Start;
}
else
{
if (state == WordState.NewWord)
{
sb.Append(wordBreakChar);
}
sb.Append(s[i]);
state = WordState.Lower;
}
}
sb.Replace("Number", "#");
return sb.ToString();
}
}
然后您可以将其应用于您的类型,如下所示:
Then you can apply it to your type as follows:
[JsonObject(NamingStrategyType = typeof(CustomNamingStrategy))]
public class RootObject
{
public string JobType { get; set; }
public string JobNumber { get; set; }
public int JobItemCount { get; set; }
public string ISOCode { get; set; }
public string SourceXML { get; set; }
}
生成的JSON如下:
{
"Job Type": "job type",
"Job #": "01010101",
"Job Item Count": 3,
"ISO Code": "ISO 9000",
"Source XML": "c:\temp.xml"
}
注意:
-
如果您想将该策略应用于已经具有通过
JsonPropertyAttribute.PropertyName
,设置NamingStrategy.OverrideSpecifiedNames == true
一个>.
If you want the strategy to apply to properties that already have property names specified via
JsonPropertyAttribute.PropertyName
, setNamingStrategy.OverrideSpecifiedNames == true
.
要将命名策略应用于所有类型,而不是在每个对象上进行设置,可以在 JsonSerializerSettings.ContractResolver
.
To apply your naming strategy to all types rather than setting it on each object, you can set the naming strategy in DefaultContractResolver.NamingStrategy
, then set the contract resolver in JsonSerializerSettings.ContractResolver
.
命名策略从c#属性名称映射到JSON属性名称,反之亦然.因此,您需要插入空格而不是拔出"并将"Number"替换为#".然后由合同解析器缓存该映射,并在反序列化过程中进行反向查找.
The naming strategy maps from the c# property name to the JSON property name, not vice versa. Thus you need to insert spaces rather than "pluck them out" and replace "Number" with "#". The mapping is then cached by the contract resolver and a reverse lookup is done during deserialization.
这篇关于使用Json.NET进行序列化时,如何应用重新映射所有属性名称的通用规则?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!