简体   繁体   中英

Newtonsoft.Json - Deserialize JSON to a custom JObject

I've got this structure from API.

[
  {
    "Id": 611932,
    "ProjectId": 6079,
    "Title": "Issue1"
    "Viewpoints": [
      {
        "Id": 885758,
        "IssueId": 611932,
        "Pinpoint": {
          "Position": {
            "X": -32.452857971191406,
            "Y": -14.971426010131836,
            "Z": 9.1110143661499023
          }
        }
      },
      {
        "Id": 885764,
        "IssueId": 611932,
        "Pinpoint": {
          "Position": {
            "X": -21.042057037353516,
            "Y": -21.742080688476563,
            "Z": 7.72857141494751
          }
        }
      }
    ]
  },
  {
    "Id": 611931,
    "ProjectId": 6079,
    "Title": "Issue2",
    "Viewpoints": [
      {
        "Id": 885757,
        "IssueId": 611931
      },
      {
        "Id": 885762,
        "IssueId": 611931,
        "Pinpoint": {
          "Position": {
            "X": -29.135581970214844,
            "Y": -14.971452713012695,
            "Z": 7.0672616958618164
          }
        }
      }
    ]
  },
  {
    "Id": 611930,
    "ProjectId": 6079,
    "Title": "Issue3",
    "Viewpoints": [
      {
        "Id": 885756,
        "IssueId": 611930,
      }
    ]
  }
]

I want to be able to construct a new structure containing all "Pinpoint" from all "Viewpoints" in form of objects so the resulting structure would look something like this (it doesn't have to be in an array it can also be contained as a new object):

[
  {
    "Id": 885758,
    "IssueId": 611932,
    "Pinpoint": {
      "Position": {
        "X": -32.452857971191406,
        "Y": -14.971426010131836,
        "Z": 9.1110143661499023
      }
    }
  },
  {
    "Id": 885764,
    "IssueId": 611932,
    "Pinpoint": {
      "Position": {
        "X": -21.042057037353516,
        "Y": -21.742080688476563,
        "Z": 7.72857141494751
      }
    }
  },
  {
    "Id": 885762,
    "IssueId": 611931,
    "Pinpoint": {
      "Position": {
        "X": -29.135581970214844,
        "Y": -14.971452713012695,
        "Z": 7.0672616958618164
      }
    }
  }
]

Note that I didn't include the "Viewpoint" array from Issue3 & one part of the "Viewpoint" array from issue2 because they didn't contain a "Pinpoint"...

Any ideas on how to achieve this? I've tried so far to add each "Position" object to the list only for testing purposes :

var jArray = JsonConvert.DeserializeObject<dynamic>(response.Content);

List<JToken> results = new List<JToken>();

foreach (JObject jObject in jArray)
{
    results.Add(new JObject(jObject["Viewpoints"].Children()["Pinpoint"]["Position"]));
}

However I get this error:

Can not add Newtonsoft.Json.Linq.JObject to Newtonsoft.Json.Linq.JObject.

Working with System.Linq .

using System.Linq;

Solution 1

  1. Add range for JObject elements in jObject["Viewpoints"] array.
  2. With . Where() filter the JObject contains "Pinpoint" property.
foreach (JObject jObject in jArray)
{   
    results.AddRange(jObject["Viewpoints"].Children());
}
        
        
results = results
    .Where(x => x["Pinpoint"] != null)
    .ToList();

To get "Position" objects only:

results = results
    .Where(x => x["Pinpoint"] != null && x["Pinpoint"]["Position"] != null)
    .Select(x => x["Pinpoint"]["Position"])
    .ToList();

Solution 2

This solution works the same concept as Solution 1 .

List<JToken> results = JArray.Parse(response.Content)
    .SelectMany(x => x["Viewpoints"])
    .Where(x => x["Pinpoint"] != null)
    .ToList();

To get "Position" objects only:

List<JToken> results = JArray.Parse(json)
    .SelectMany(x => x["Viewpoints"])
    .Where(x => x["Pinpoint"] != null && x["Pinpoint"]["Position"] != null)
    .Select(x => x["Pinpoint"]["Position"])
    .ToList();

Sample .NET Fiddle

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM