将注意的命名空间字符串的点列表中的列表中列入嵌套的JSON字符串C#



我如何将注明的名称空间字符串的列表对嵌套的JSON字符串进行排序?

类似的东西。

var string1 = "example.string.1";
var string2 = "example.string.2";
var string3 = "example.anotherstring.1";

整理了这个。

{
    "example": {
        "string": ["1", "2"],
        "anotherstring": ["1"]
    }
}

编辑1

谢谢!我能够使用您的答案接近工作。

在此列表中,它有效:

var strings = new List<string>
{
    "example.string.1",
    "example.string.2",
    "example.anotherstring.1",
};
public void Example()
{
    var dict = new Dictionary<string, dynamic>();
    foreach (var s in strings)
    {
        AddPartsToDictionary(dict, s.Split('.'));
    }
}
public void AddPartsToDictionary(IDictionary<string, dynamic> dict, string[] parts)
{
    for (var i = 0; i < parts.Length; i++)
    {
        if (i < parts.Length - 2)
        {
            if (!dict.ContainsKey(parts[i]))
                dict.Add(parts[i], new Dictionary<string, dynamic>());
            dict = dict[parts[i]];
        }
        else if (i < parts.Length - 1)
        {
            if (!dict.ContainsKey(parts[i]))
            {
                var list = new List<string>();
                dict[parts[i]] = list;
            }
        }
        else
        {
            var list = dict[parts[i - 1]] as List<string>;
            list.Add(parts[i]);
        }
    }
}

结果JSON

{
    "example":  {
        "string":  [
            "1",
            "2"    
    ],
        "anotherstring":  [
            "1"    
    ]  
  }
}

在此列表中,它失败了

var strings = new List<string>
{
    "example.string.1",
    "example.string.example.1",
    "example.string.2",
    "example.anotherstring.1",
    "example.string.example.2",
    "string.example.2"
};

我可能必须对列表或其他内容进行排序,但仍在努力。希望这有助于弄清楚它。

对象一直向下

如果使用对象(代替数组(一直都可以,则可以正常工作。

var strings = new List<string> {
    "example.string.1",
    "example.string.2",
    "example.anotherstring.1",
};
var result = strings.Aggregate(new Dictionary<string, Object>(), (acc, s) =>
{
    var level = acc;
    foreach(var segment in s.Split('.'))
    {
        if (!level.ContainsKey(segment))
        {
            var child = new Dictionary<string, Object>();
            level.Add(segment, child);
        }
        level = level[segment] as Dictionary<string, Object>;
    }
    return acc;
});
var json = JsonConvert.SerializeObject(result, Formatting.Indented);

输出一直都有对象。

{
  "example": {
    "string": {
      "1": {},
      "2": {}
    },
    "anotherstring": {
      "1": {}
    }
  }
}

在最后级别(带小提琴(

如果您想在最后级别进行数组,那么我们需要对定义最后一个级别的确切定义。例如,最后一个级别是否总是包含整数?如果是这样,以下有效。

var result = strings.Aggregate(new Dictionary<string, Object>(), (acc, s) =>
{
    Dictionary<string, Object> previousLevel = null;
    Dictionary<string, Object> nextLevel = acc;
    string previousSegment = null;
    foreach (string nextSegment in s.Split('.'))
    {
        if (Int16.TryParse(nextSegment, out _))
        {
            if (previousLevel[previousSegment] is Dictionary<string, Object>)
            {
                previousLevel[previousSegment] = new List<string>();
            }
            var list = previousLevel[previousSegment] as List<string>;
            list.Add(nextSegment);
        }
        else
        {
            if (!nextLevel.ContainsKey(nextSegment))
            {
                var child = new Dictionary<string, Object>();
                nextLevel.Add(nextSegment, child);
            }
            previousSegment = nextSegment;
            previousLevel = nextLevel;
            nextLevel = nextLevel[nextSegment] as Dictionary<string, Object>;
        }
    }
    return acc;
});

输出在最后级别。

{
  "example": {
    "string": [
      "1",
      "2"
    ],
    "anotherstring": [
      "1",
      "2"
    ]
  }
}

此数组版本仅在最后一个级别仅是integer类型的情况下才能工作,这是您最初的问题所需的。

更困难的情况是在同一级别上处理混合的stringinteger类型,该级别的输入看起来像这样:

"System.1", 
"System.2", 
"System.Collections.1", 
"System.Collections.2", 
"System.Collections.Generic.1"

需要更复杂的算法。如果这是隐藏的要求,请考虑在此答案的评论中提出一个全新的后续问题并链接到它。

我以为id快速地走了,它接近但不是您想要的。但是我认为这可能会激发您或其他人尝试。

免责声明,我不是真正的 json.net aficionado,此代码是 相当不错。不寻常,至少要说

演示此处


给定列表

var list = new List<string>
   {
      "example.string.1",
      "example.string.2",
      "example.anotherstring.1",
      "example.anotherstring.2",
      "System",
      "System.Diagnostics",
      "System.Text",
      "System.Collections.Generic",
      "System.Linq",
      "System.Diagnostics.1",
      "System.Text.1",
      "System.Collections.Generic.1",
      "System.Linq.1",
      "System.Diagnostics.2",
      "System.Text.2",
      "System.Collections.Generic.2",
      "System.Linq.2"
   };

一些类

public class RawValue
{
   public RawValue(string key, IEnumerable<IEnumerable<string>> values)
   {
      Key = key;
      Values = values;
   }
   public string Key { get; set; }
   public IEnumerable<IEnumerable<string>> Values { get; set; }
}
public class NameSpace : Dictionary<string, NameSpace>
{
}

一些帮助者

private static IEnumerable<RawValue> GetRawValues(RawValue value)
{
   return value.Values.Where(x => x.Any())
               .GroupBy(x => x.FirstOrDefault())
               .Select(x => new RawValue(x.Key, x.Select(y => y.Skip(1))));
}
private static NameSpace GroupNameSpaces(IEnumerable<RawValue> groups)
{
   var result = new NameSpace();
   foreach (var group in groups)
      result.Add(group.Key, GroupNameSpaces(GetRawValues(group)));
   return result;
}

主代码

var groups = list.Select(x => x.Split('.'))
                  .GroupBy(x => x.FirstOrDefault())
                  .Select(x => new RawValue(x.Key, x.Select(y => y.Skip(1))));
var settings = new JsonSerializerSettings
   {
      NullValueHandling = NullValueHandling.Ignore
   };
var result = GroupNameSpaces(groups);
var json = JsonConvert.SerializeObject(result, Formatting.Indented, settings);
Console.WriteLine(json);

输出

{
  "example": {
    "string": {
      "1": {},
      "2": {}
    },
    "anotherstring": {
      "1": {},
      "2": {}
    }
  },
  "System": {
    "Diagnostics": {
      "1": {},
      "2": {}
    },
    "Text": {
      "1": {},
      "2": {}
    },
    "Collections": {
      "Generic": {
        "1": {},
        "2": {}
      }
    },
    "Linq": {
      "1": {},
      "2": {}
    }
  }
}

我认为由于我不知道如何在 json.net 中更好地序列化的事实,我的失败必须使用NameSpace : Dictionary<string, NameSpace>。同样,我不花时间在此上,我无法弄清楚如何将最后一个节点转换为JSON数组。尽管我不确定您是否可以考虑。但是我确定可以做得更好

最新更新