Получите свойство JObject из JObject, у которого есть определенное другое значение свойства - PullRequest
1 голос
/ 25 октября 2019

Я относительно свободно использую json.net, но я изо всех сил пытаюсь получить это значение простым способом.

Я чувствую, что json.net должен быть в состоянии вывести то, что я пытаюсьсделайте так, чтобы мне не приходилось делать каждый шаг по пути, чтобы получить то, что я хочу.

Ниже моя первая неудачная попытка и вторая попытка, с которой я приступил к работе. Хотя вторая попытка работает, я хотел бы упростить код, чтобы он был немного похож на первый.

Обратите внимание, что я не могу предположить, что объект "C" - это тот, который содержит объектЯ хочу.

var jt = JToken.Parse(@"{
    ""A"": {
        ""name"": ""object1"",
        ""order"": ""1"",
        ""type"": ""val""
    },
    ""B"": {
        ""order"": ""2"",
        ""type"": ""val"",

    },
    ""C"": {
        ""name"": ""object3"",
        ""type"": ""val"",
        ""answer"": ""Yes"", ""<------ comment"": ""this is the value I'm trying to get""
    }
}");

//var firstAttempt = (jt.First(j => j["name"] == "object3"))["answer"];  // cannot be applied to operands of type 'JToken' and 'String'

var thisWorksFine = jt.First(a => a.ToObject<JProperty>()
                            .Value.ToObject<JObject>()["name"]?.ToString() == "object3")
                            .ToObject<JProperty>()
                            .Value["answer"];

Итак, мой вопрос: есть ли способ получить значение без приведения каждого объекта / свойства и в конечном итоге получить код, который больше похож на мою первую попытку? Если моя вторая попытка более или менее необходима, это нормально.

Ответы [ 3 ]

1 голос
/ 25 октября 2019

Вы специально хотите всегда получать ответ под объектом "C"?

Если это так, вы можете использовать:

var jToken = JToken.Parse("{\r\n\t\"A\": {\r\n\t\t\"name\": \"object1\",\r\n\t\t\"order\": \"1\",\r\n\t\t\"type\": \"val\"\r\n\t},\r\n\t\"B\": {\r\n\t\t\"name\": \"object2\",\r\n\t\t\"order\": \"2\",\r\n\t\t\"type\": \"val\"\r\n\t},\r\n\t\"C\": {\r\n\t\t\"name\": \"object3\",\r\n\t\t\"type\": \"val\",\r\n\t\t\"answer\": \"Yes\"\r\n\t}\r\n}");

var answer = jToken.SelectToken("C.answer");
1 голос
/ 25 октября 2019

Вы, кажется, прыгаете через большее количество обручей, чем нужно. Я бы переписал ваш запрос следующим образом:

var answer = jt.Children<JProperty>()
               .Where(jp => (string)jp.Value["name"] == "object3")
               .Select(jp => (string)jp.Value["answer"])
               .FirstOrDefault();

Fiddle: https://dotnetfiddle.net/blKne6

Вышесказанное можно несколько упростить до следующего, что немного ближе к вашей первой попытке:

var answer = (string)jt.Children<JProperty>()
                       .FirstOrDefault(jp => (string)jp.Value["name"] == "object3")
                       ?.Value["answer"];

Скрипка: https://dotnetfiddle.net/3Iw8Uu

1 голос
/ 25 октября 2019

Я использовал QuickType , чтобы создать модель вашего кода Json, а затем проанализировал ее и выполнил фильтрацию полученных объектов, что намного проще. Код:

public class MyElement
{
    [JsonProperty("name")]
    public string Name { get; set; }

    [JsonProperty("order")]
    public long Order { get; set; }

    [JsonProperty("type")]
    public string Type { get; set; }

    [JsonProperty("answer")]
    public string Answer { get; set; }
}

И разбор:

string json = @"{
    ""A"": {
        ""name"": ""object1"",
        ""order"": ""1"",
        ""type"": ""val""
    },
    ""B"": {
        ""order"": ""2"",
        ""type"": ""val"",

    },
    ""C"": {
        ""name"": ""object3"",
        ""type"": ""val"",
        ""answer"": ""Yes"",
    }
}";

Dictionary<string, MyElement> elements = JsonConvert.DeserializeObject<Dictionary<string, MyElement>>(json);
string answerOfObject3 = elements.Values.FirstOrDefault(element => element.Name == "object3")?.Answer;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...