0

I have a web api controller in .NET Core 2.1, which receives

JToken jsonBody

The json has the following structure

{
  "id": "xxx",
  "payload": {
    "TelephoneNumber": "1111",
    "Name": "Hans"
  }
}

and more fields, but it's irrelevant. I want to retrieve the Number and Name elegantly. Currently, I do the following, which I'm sure could be done in a nicer way:

var payload = JObject.Parse(jsonBody.SelectToken("Payload").ToString());
            telephoneNumber = new TelephoneNumber(payload.SelectToken("TelephoneNumber").ToString());

I've tried just doing

jsonBody.SelectToken("Payload.TelephoneNumber")

but that doesn't work. I think that it's because somehow the jsonBody, that the controller receives, has only parsed the top nodes as json, hence it could be that it regards the value of

jsonBody.SelectToken("Payload")

as a string.

Rui Jarimba
  • 11,166
  • 11
  • 56
  • 86
SabrinaMH
  • 221
  • 1
  • 3
  • 11
  • 1
    https://www.newtonsoft.com/json/help/html/QueryingLINQtoJSON.htm – Zohar Peled Nov 01 '18 at 10:23
  • 1
    I suspect SelectToken returns a JObject already – Panagiotis Kanavos Nov 01 '18 at 10:29
  • Possible duplicate of [Getting a specific field from a JSON string without deserializing in C#](https://stackoverflow.com/questions/37291102/getting-a-specific-field-from-a-json-string-without-deserializing-in-c-sharp) – SᴇM Nov 01 '18 at 10:30
  • 1
    You need to do `jsonBody.SelectToken("payload.TelephoneNumber")` not `jsonBody.SelectToken("Payload.TelephoneNumber")` because JSONPath is **case sensitive**. Otherwise, `SelectToken()` works, see https://dotnetfiddle.net/TgLsDj. – dbc Nov 01 '18 at 20:49

3 Answers3

2

As per official documentation - you can do something like this:

var phone = jsonBody["payload"]["TelephoneNumber"].ToString();
var name = jsonBody["payload"]["Name"].ToString();

See a live demo on rextester.

Zohar Peled
  • 79,642
  • 10
  • 69
  • 121
  • This doesn't work. If I do var test = jsonBody["Payload"]["TelephoneNumber"], then I get the following error "Cannot access child value on Newtonsoft.Json.Linq.JValue." – SabrinaMH Nov 01 '18 at 12:43
  • Then you are doing it wrong. See the live demo I've linked to in my answer. I get correct results. – Zohar Peled Nov 01 '18 at 13:10
1

This is at least a little bit more elegant:

var jsonBody = JObject.Parse(@"{
  'id': 'xxx',
  'payload': {
    'TelephoneNumber': '1111',
    'Name': 'Hans'
  }
}");

var phone = jsonBody["payload"]["TelephoneNumber"].Value<string>();
var name = jsonBody["payload"]["Name"].Value<string>();
Erlend D.
  • 3,013
  • 6
  • 37
  • 59
  • This doesn't work. If I do var test = jsonBody["Payload"]["TelephoneNumber"], then I get the following error "Cannot access child value on Newtonsoft.Json.Linq.JValue." – SabrinaMH Nov 01 '18 at 12:42
  • 2
    Did you try with lowercase "payload"? The JSON is case sensitive. – Erlend D. Nov 01 '18 at 14:43
  • Also make sure that "jsonBody" actually is a JObject or a JToken (and not a "JValue", as it sounds like it is from your error message). – Erlend D. Nov 01 '18 at 14:50
0

If you don't want to deserialize your full json, you can create a class with the properties you need

public class Payload
{
    public string TelephoneNumber { get; set; }
    public string Name { get; set; }
}

And then use JsonTextReader to deserialize the string:

private static Payload DeserializePayload(JToken token)
{
    var serializer = new JsonSerializer();

    using (JsonTextReader reader = new JsonTextReader(new StringReader(token.ToString())))
    {
        reader.CloseInput = true;

        while (reader.Read())
        {
            if (reader.TokenType == JsonToken.StartObject && reader.Path.Equals("payload"))
            {
                var payload = serializer.Deserialize<Payload>(reader);
                return payload;
            }
        }
    }

    // not found - return null? throw exception?
    return null;
}

Testing the code:

var token = JToken.Parse(@"{
  ""id"": ""xxx"",
  ""payload"": {
    ""TelephoneNumber"": ""1111"",
    ""Name"": ""Hans""
  }
}");

Payload payload = DeserializePayload(token);

Console.WriteLine($"Name: {payload.Name}, Phone number: {payload.TelephoneNumber}");
Rui Jarimba
  • 11,166
  • 11
  • 56
  • 86