Matt Douhan
Matt Douhan

Reputation: 2113

How can I convert JToken to string[]?

I am trying to read an array from a JObject into a string[] but I cannot figure out how.

The code is very simple as below but does not work. Fails with error cannot convert JToken to string[]

JObject Items = jsonSerializer.Deserialize<JObject>(jtr);
string[] brands = null;
brands = (string[])Items.SelectToken("Documents[0].Brands");

The following works when I want to read a simple bool so I know I am in the right place.

IsAdmin = (bool)Items.SelectToken("Documents[0].IsAdmin");

the JObject in Documents[0] looks as follows

{
    "id": "961AA6A6-F372-ZZZZ-1270-ZZZZZ",
    "ApiKey": "SDKTest",
    "ConsumerName": "SDKTest",
    "IsAdmin": false,
    "Brands": [
        "ZZZ"
    ],
    "IsSdkUser": true
}

How can I read that Brands array into my string[] brands?

Upvotes: 30

Views: 55322

Answers (4)

Dmitry Shashurov
Dmitry Shashurov

Reputation: 1704

public static T[] JTokenToArray<T>(JToken jToken)
{
    List<T> ret = new List<T>();
    foreach (JToken jItem in jToken)
        ret.Add(jItem.Value<T>());
    return ret.ToArray();
}

Usage:

string[] brands = JTokenToArray<string>(jObject.Value<JToken>("brands"));

Upvotes: 1

dbc
dbc

Reputation: 116595

You can use JToken.ToObject<T>() to deserialize a JToken to any compatible .Net type, i.e.

var brands = Items.SelectToken("Documents[0].Brands")?.ToObject<string []>();

Casting operations on JToken such as (bool)Items.SelectToken("Documents[0].IsAdmin") only work for primitive types for which Newtonsoft has supplied an explicit or implicit conversion operator, all of which are documented in JToken Type Conversions. Since no such conversion operator was implemented for string[], deserialization is necessary.

Demo fiddle here.

Upvotes: 32

Joel Wiklund
Joel Wiklund

Reputation: 1875

  1. Create C# classes from the below json using this tool or in VS Edit > Paste Special > Paste JSON As Classes.
  2. Install Newtonsoft.Json Nuget package
  3. Use JsonConvert.DeserializeObject to deserialize the json to C# classes.
  4. The root object now contains everything you've ever wanted!

file.json

{
  "Documents": [
    {
      "id": "961AA6A6-F372-ZZZZ-1270-ZZZZZ",
      "ApiKey": "SDKTest",
      "ConsumerName": "SDKTest",
      "IsAdmin": false,
      "Brands": [
        "ZZZ"
      ],
      "IsSdkUser": true
    }
  ]
}

Program.cs

using System.IO;
using Newtonsoft.Json;

public class Program
{
    static void Main(string[] args)
    {
        using (StreamReader r = new StreamReader(@"file.json"))
        {
            string json = r.ReadToEnd();
            var root = JsonConvert.DeserializeObject<RootObject>(json);
            var brands = root.Documents[0].Brands; // brands = {"ZZZ"}
        }
    }
}

public class RootObject
{
    public Document[] Documents { get; set; }
}

public class Document
{
    [JsonProperty("id")]
    public string Id { get; set; }
    public string ApiKey { get; set; }
    public string ConsumerName { get; set; }
    public bool IsAdmin { get; set; }
    public string[] Brands { get; set; }
    public bool IsSdkUser { get; set; }
}

Upvotes: 4

Innat3
Innat3

Reputation: 3576

You can use .Values<T> to retrieve the values of the JToken and cast them to the desired type.

var brands = Items["Documents"][0]["Brands"].Values<string>().ToArray();

Upvotes: 4

Related Questions