使用Json.NET进行序列化时,如何应用重新映射所有属性名称的通用规则? [英] How to apply a general rule for remapping all property names when serializing with Json.NET?

查看:99
本文介绍了使用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 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"
}

注意:

  • If you want the strategy to apply to properties that already have property names specified via JsonPropertyAttribute.PropertyName, set NamingStrategy.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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆