【问题标题】:Finding a JSON entry and add a nested element查找 JSON 条目并添加嵌套元素
【发布时间】:2016-08-24 10:07:58
【问题描述】:

我有一个如下所示的 .json 文件:

[
  {
    "username": "John",
    "currency": 8,
    "pulls": 
    [
      {
        "character": "person"
      },
      {
        "character": "loved one"
      }
    ]
  },
  {
    "username": "Mike",
    "currency": 2,
    "pulls": 
    [
      {
        "character": "noone" 
      }
    ]
  },
  {
    "username": "Clara",
    "currency": 5,    
    "pulls": 
    [
      {
        "character": "someone" 
      }
    ]
  }
] 

到目前为止我设法做的是修改“货币”:

    bool userExists = false;
    string jsonPointsString = File.ReadAllText(userPath);
    dynamic jsonObjects = JsonConvert.DeserializeObject(jsonPointsString);
    foreach (var jsonObject in jsonObjects)
    {
        if (jsonObject["username"] == user)
        {
            jsonObject["currency"] += value;
            string output = JsonConvert.SerializeObject(jsonObjects, Formatting.Indented);
            File.WriteAllText(userPath, output);
            userExists = true;
        }
    }

以及从头开始添加一个全新的条目:

    JsonCollection.User user = new JsonCollection.User();
    user.username = username;
    user.currency = 10;
    using (StreamReader r = new StreamReader(userPath))
    {
        string json = r.ReadToEnd();
        List<JsonCollection.User> users = JsonConvert.DeserializeObject<List<JsonCollection.User>>(json);
        users.Add(user);
        newJson = JsonConvert.SerializeObject(users, Formatting.Indented);
    }
    File.WriteAllText(userPath, newJson);

但是,无论我尝试什么,我都无法向“拉动”添加另一个元素。这个想法是我用一个用户名和一个拉取两个字符串来调用一个函数。基于用户名变量,我必须找到相应的 Json 条目并根据拉变量在“拉”树中创建一个新条目。这是我能想到的:

    public void AddPullToUser(string user, string newPull)
    {
        user = "Mike";  //test value

        string jsonPointsString = File.ReadAllText(userPath);
        dynamic jsonObjects = JsonConvert.DeserializeObject(jsonPointsString);
        foreach (var jsonObject in jsonObjects)
        {
            if (jsonObject["username"] == user)
            {
                //jsonObject["pulls"] = newPull;

                JsonCollection.Character pull = new JsonCollection.Character();
                pull.character = newPull;
                jsonObject["pulls"] = pull;

                string output = JsonConvert.SerializeObject(jsonObjects, Formatting.Indented);
                File.WriteAllText(userPath, output);

            }
        }
    }

如果我这样做,系统将无法将 JsonCollection 转换为 JArray 但不使用 JArray 我不明白如何找到特定的用户树。 在第二步中,这必须进一步扩展,以免产生重复的“拉动”,但首先这必须正常工作。

任何帮助将不胜感激。

【问题讨论】:

  • 您可以将json反序列化为强类型C#对象,然后修改您想要的条目。我认为这会更容易。
  • 查看link

标签: c# json json.net


【解决方案1】:

类似的东西-

var json = "[{'username':'John','currency':8,'pulls':[{'character':'person'},{'character':'loved one'}]},{'username':'Mike','currency':2,'pulls':[{'character':'noone'}]},{'username':'Clara','currency':5,'pulls':[{'character':'someone'}]}]";
var obj = JsonConvert.DeserializeObject<List<RootObject>>(json);
var o = obj.FindIndex(a => a.username == "Mike");
obj[o].pulls.AddRange(new List<Pull>{
        new Pull{
            character = "Modified"
        }
    });

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

在哪里

public class Pull
{
    public string character { get; set; }
}

public class RootObject
{
    public string username { get; set; }
    public int currency { get; set; }
    public List<Pull> pulls { get; set; }
}

或者,您可能对JSON Merge感兴趣

一个可能的解决方案看起来像 -

var json = "[{'username':'John','currency':8,'pulls':[{'character':'person'},{'character':'loved one'}]},{'username':'Mike','currency':2,'pulls':[{'character':'noone'}]},{'username':'Clara','currency':5,'pulls':[{'character':'someone'}]}]";
var obj = JArray.Parse(json);
var idx = obj.IndexOf(obj.FirstOrDefault(a => a["username"].ToString() == "Mike"));     
((JArray)obj[idx]["pulls"]).Add(JObject.Parse(@"{
        'character': 'new one'
    }"));
Console.WriteLine(obj[idx]);
/*output - 
 {
   "username": "Mike",
   "currency": 2,
   "pulls": [
     {
        "character": "noone"
     },
     {
        "character": "new one"
     }
  ]
} */

【讨论】:

  • 谢谢!根据您的示例,我能够找到一个解决方案,我将在我的问题答案中写下。
【解决方案2】:

经过更多研究和您的帮助,我首先能够将与 Json 的所有交互更改为相同的代码样式。

新条目已更改为:

    public void CreateUser(string username)
    {
        try
        {
            string jsonUserString = File.ReadAllText(userPath);
            var users = JsonConvert.DeserializeObject<List<JsonCollection.User>>(jsonUserString);
            users.AddRange(new List<JsonCollection.User> { new JsonCollection.User { username = username, currency = 10, pulls = new List<JsonCollection.Character> { new JsonCollection.Character { character = "TemmieHYPE" } } } });
            string output = JsonConvert.SerializeObject(users, Formatting.Indented);
            File.WriteAllText(userPath, output);
        }
        catch
        {
            Console.WriteLine("Error on CreateUser");
        }
    }

更新已更改为:

    public void UpdateUserStats(string username, decimal value, int selection)
    {
        try
        {
            string jsonUserString = File.ReadAllText(userPath);
            var users = JsonConvert.DeserializeObject<List<JsonCollection.User>>(jsonUserString);
            int user = users.FindIndex(a => (a.username == username));
            if (user != -1)
            {
                switch (selection)
                {
                    case 1:
                        users[user].currency += value;
                        break;
                    case 2:
                        users[user].secondsOnline += value;
                        break;
                    default:
                        break;
                }

                string output = JsonConvert.SerializeObject(users, Formatting.Indented);
                File.WriteAllText(userPath, output);

                //AddPullToUser(username, DateTime.Now.ToString());  //remove on live
            }
            else
            {
                CreateUser(username);
            }
        }
        catch 
        {
            Console.WriteLine("Error on UpdateCurrency");
        }
    }

最重要的是,用于向 Json 添加嵌套元素的 Add Pull 命令现在可以使用以下代码:

    public void AddPullToUser(string username, string pulledCharacter)
    {
        string jsonUserString = File.ReadAllText(userPath);
        var users = JsonConvert.DeserializeObject<List<JsonCollection.User>>(jsonUserString);
        int alreadyPulled = users.FindIndex(a => (a.username == username) && (a.pulls.FindIndex(b => b.character == pulledCharacter) > 0));
        if (alreadyPulled == -1)
        {
            int user = users.FindIndex(a => (a.username == username));
            users[user].pulls.AddRange(new List<JsonCollection.Character> { new JsonCollection.Character { character = pulledCharacter } });
            string output = JsonConvert.SerializeObject(users, Formatting.Indented);
            File.WriteAllText(userPath, output);
        }
    }

添加“if (alreadyPulled == -1)”后,重复的 pull 也不会添加到 Json 文件中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-06
    • 2019-08-18
    相关资源
    最近更新 更多