【问题标题】:Change the property names in a JSON object before conversion to XML在转换为 XML 之前更改 JSON 对象中的属性名称
【发布时间】:2016-10-18 01:41:46
【问题描述】:

我正在尝试将一些 JSON 转换为 XML,但在此之前我需要更改一些属性才能成功转换。

JSON 结构中的某些属性以数字开头,当我尝试转换为 XML 时,我收到错误消息,因为 XML 不允许以数字开头的标签。

因此,一种对我有用的解决方案是通过向属性添加前缀来更改以数字开头的那些属性名称。

我一直在尝试做这样的事情:

public string ChangeNumericalPropertyNames(JsonReader reader)
{
    JObject jo = JObject.Load(reader);

    foreach (JProperty jp in jo.Properties())
    {
        if (Regex.IsMatch(jp.Name, @"^\d"))
        {
            string name = "n" + jp.Name; 

            //Logic to set changed name
        }
    }

    return "Here I want to return the entire json string with changed names";
}

当我尝试这个时:

jp.Name = name;

Visual Studio 说这是不可能的,因为 jp.Name 是只读的。

有人知道如何实现这个解决方案吗?

【问题讨论】:

  • 替换json字符串中的属性名,然后序列化json。
  • 不是那么简单,因为我不知道如何设置名称。不可能做类似 jp.Name = name 的事情,因为 jp.Name 是只读的
  • 获取您的 json 字符串并修改它 - idk,执行 Regex.Replace() 然后序列化修改后的字符串。

标签: c# json xml json.net


【解决方案1】:

由于属性名称是只读的,因此您需要替换整个属性。您可以使用Replace 方法来执行此操作:

        if (Regex.IsMatch(jp.Name, @"^\d"))
        {
            string name = "n" + jp.Name;
            jp.Replace(new JProperty(name, jp.Value));
        }

然而,这会导致另一个问题——因为你试图修改 JObject 的 Properties 集合,同时迭代它,Json.Net 将抛出一个 InvalidOperationException。要解决此问题,您必须将属性复制到单独的列表并对其进行迭代。您可以使用 foreach 中的 ToList() 方法来做到这一点,如下所示:

    foreach (JProperty jp in jo.Properties().ToList())

最后,要将更新后的 JObject 转换回 JSON,只需使用 ToString(). 将它们放在一起,我们就有了:

public static string ChangeNumericalPropertyNames(JsonReader reader)
{
    JObject jo = JObject.Load(reader);

    foreach (JProperty jp in jo.Properties().ToList())
    {
        if (Regex.IsMatch(jp.Name, @"^\d"))
        {
            string name = "n" + jp.Name;
            jp.Replace(new JProperty(name, jp.Value));
        }
    }

    return jo.ToString();
}

小提琴:https://dotnetfiddle.net/rX4Jyy


上述方法只会处理一个简单的 JSON 对象,其属性都在一个级别上。您在评论中指出,您的实际 JSON 不是平面的,而是分层的。为了替换层次结构中的所有数字属性名称,您需要使您的方法递归,如下所示:

public static string ChangeNumericalPropertyNames(JsonReader reader)
{
    JObject jo = JObject.Load(reader);
    ChangeNumericalPropertyNames(jo);
    return jo.ToString();
}

public static void ChangeNumericalPropertyNames(JObject jo)
{
    foreach (JProperty jp in jo.Properties().ToList())
    {
        if (jp.Value.Type == JTokenType.Object)
        {
            ChangeNumericalPropertyNames((JObject)jp.Value);
        }
        else if (jp.Value.Type == JTokenType.Array)
        {
            foreach (JToken child in jp.Value)
            {
                if (child.Type == JTokenType.Object)
                {
                    ChangeNumericalPropertyNames((JObject)child);
                }
            }
        }

        if (Regex.IsMatch(jp.Name, @"^\d"))
        {
            string name = "n" + jp.Name;
            jp.Replace(new JProperty(name, jp.Value));
        }
    }
}

小提琴:https://dotnetfiddle.net/qeZK1C

【讨论】:

  • 首先,感谢您的帮助。我尝试了您的解决方案,它适用于同一级别的属性。但是当json是这样的时候我有一个例外,{1:“一”,2:{3:“三”}}当数字名称是另一个属性的属性时。
  • 你需要一个递归方法来处理它。我已经更新了我的答案。
  • 非常感谢您的帮助!
猜你喜欢
  • 2020-02-02
  • 2021-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多