如何通过匹配值从JSON字符串中的特定属性中删除值?

时间:2016-10-05 08:06:31

标签: c# .net json linq json.net

我有一个像这样的JSON字符串:

{"Country":"USA","States":["Chicago","Miami"]}

public string Remove(string json)
{
    string[] stateFilter = { "Chicago", "Miami"};
    foreach (var state in stateFilter)
    {
        //here I would like to create new copy of json for each state.
        string newJson = {"Country":"USA","States":["Chicago"]}  // Removed Miami from json for Chicago
    }
}

现在,我想通过在JSON中查找状态并从JSON字符串中删除它来为每个状态创建一个新的JSON字符串。因此,每个州都将包含其JSON的新副本,并且不包含任何其他状态。

例如:芝加哥将在JSON Chicago Property中包含States

我正在尝试的代码:

public string Remove(string json)
{
    string[] stateFilter = { "Chicago", "Miami"};
    foreach (var state in stateFilter)
    {
        var jArr = JArray.Parse(json);

        jArr.Descendants().OfType<JProperty>()
            .Where(p => p.Name == state)
            .ToList()
            .ForEach(att => att.Remove());
    }
}

但是上面的代码删除了属性而不是JSON字符串中的值。

4 个答案:

答案 0 :(得分:1)

此解决方案基于您的规范:因此每个州都将包含其json的新副本,并且不包含任何其他状态

您可以使用Newtonsoft json序列化程序反序列化json为每个状态创建新实例并将它们序列化为json

public class States
{
    public string Country { get; set; }
    public List<string> States { get; set; }        
}

public IEnumerable<string> GenerateSeparatedListOfStates(string json)
{
    var original = JsonConvert.DeserializaeObject<States>(json);

    foreach(string state in original.States)
    {
        var temp = new States 
        { 
            Country = state.Country,
            States = new List<string> { state }
        }
        yield return JsonConvert.SerializeObject(temp);
    }
}

答案 1 :(得分:1)

您需要将json反序列化为对象,从状态列表中删除不需要的对象,然后再将其序列化。

    public class JsonClass
    {
        public string Country { get; set; }

        public List<string> States { get; set; }
    }


    static void Main(string[] args)
    {
        string json = @"{""Country"":""USA"",""States"":[""Chicago"",""Miami""]}";

        JsonClass className  = JsonConvert.DeserializeObject<JsonClass>(json);

        className.States.Remove("Miami");

        Console.WriteLine(JsonConvert.SerializeObject(className));

    }

修改

关于您的问题:删除没有芝加哥的所有元素:

更改行:

className.States.Remove("Miami");

要:

className.States.RemoveAll(x => x != "Chicago");

答案 2 :(得分:1)

我已经阅读了你的所有问题和所有其他答案的评论,坦率地说,我仍然不确定这是否能回答我的想法!

此代码不需要任何外部库,您只需要在项目中添加对System.Web.Extensions的引用。

string jsonString = "{\"Country\":\"USA\",\"States\":[\"Chicago\",\"Miami\"]}";
var jss = new JavaScriptSerializer();
dynamic json = jss.DeserializeObject(jsonString);
var statesToRemove = new object[] { "Chicago", "Miami" };
object[] originalStates = json["States"] as object[];
foreach(var state in statesToRemove)
{
    json["States"] = new[] { state }; 
    string newJson = jss.Serialize(json);
}
// Outputs...
// {"Country":"USA","States":["Chicago"]}
// {"Country":"USA","States":["Miami"]}

我们将json反序列化为对象图并动态遍历它(使用dynamic - 这就是json["States"]甚至编译的方式。对于statesToRemove集合中的每个状态,我们序列化一个新的json字符串,并将其作为唯一的状态。

答案 3 :(得分:1)

如果您只是想找到一种方法来复制JSON并将States数组替换为一个已知状态,那么您可以使用这样的方法:

public static string Remove(string json, string stateToKeep)
{
    JObject jo = JObject.Parse(json);
    jo["States"] = new JArray(stateToKeep);
    return jo.ToString();
}

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

如果你想在States数组中的所有状态执行此操作而事先不知道它们是什么,那么你可以这样做:

public static string Remove(string json)
{
    var obj = JObject.Parse(json);
    var result = obj["States"].Select(s =>
    {
        var clone = s.Root.DeepClone();
        clone["States"] = new JArray(s);
        return clone;
    });
    return new JArray(result).ToString();
}

基本上,我们将JSON解析为JObject,然后使用Select迭代状态。对于每个状态,我们克隆整个JSON,然后用仅包含单个状态的新States替换克隆的JArray数组。最后,我们将所有这些克隆放入一个新的JArray并将其转换为字符串。

鉴于您的原始JSON,您最终会得到这个新结果:

[
  {
    "Country": "USA",
    "States": [
      "Chicago"
    ]
  },
  {
    "Country": "USA",
    "States": [
      "Miami"
    ]
  }
]

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