Search code examples
c#jsonlinqjson.net

Send JSON via POST in C# and Use LINQ to access Objects


I want to be able to access the JSON objects with LINQ when the JSON is returned.

I have referred to Send JSON via POST in C# and Receive the JSON returned? and Send and receive json via HttpClient

This is what I have so far

 public static async Task<string> GetMailTip(string user)
        {
            var jsonData = new StringContent(FormatJson(CreateJsonGettingMailTip(user)), Encoding.UTF8, "application/json");
            var payload = await client.PostAsync($"https://graph.microsoft.com/v1.0/users/{user}/getMailTips", jsonData);
            string responseContent = "";

            if (payload.Content != null)
            {
                responseContent = await payload.Content.ReadAsStringAsync();

                Console.WriteLine(responseContent);
            }

            var getMailTip = responseContent["value"]
              .Children()
              .Where(i => i != null)
              .Select(c => c[""][""].Value<string>().Trim());

            return responseContent;
        }

The returned JSON is

{
    "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#Collection(microsoft.graph.mailTips)",
    "value": [
        {
            "emailAddress": {
                "name": "",
                "address": ""
            },
            "automaticReplies": {
                "message": "",
                "messageLanguage": {
                    "locale": "",
                    "displayName": ""
                },
                "scheduledStartTime": {
                    "dateTime": "",
                    "timeZone": ""
                },
                "scheduledEndTime": {
                    "dateTime": "",
                    "timeZone": ""
                }
            }
        }
    ]
}

I want to be able to access the message property in the JSON with LINQ

Any help would be appreciated


Solution

  • You go to http://quicktype.io (or similar online service, jsonutils, json2csharp, or use the Visual studio Paste Json as Classes feature - of all the sites that do this QT is the most full featured) to turn your json into classes. This makes it nicer to work with:

    // <auto-generated />
    //
    // To parse this JSON data, add NuGet 'Newtonsoft.Json' then do:
    //
    //    using SomeNamespaceHere;
    //
    //    var rootClassNameHere = RootClassNameHere.FromJson(jsonString);
    
    namespace SomeNamespaceHere
    {
        using System;
        using System.Collections.Generic;
    
        using System.Globalization;
        using Newtonsoft.Json;
        using Newtonsoft.Json.Converters;
    
        public partial class RootClassNameHere
        {
            [JsonProperty("@odata.context")]
            public Uri OdataContext { get; set; }
    
            [JsonProperty("value")]
            public Value[] Value { get; set; }
        }
    
        public partial class Value
        {
            [JsonProperty("emailAddress")]
            public EmailAddress EmailAddress { get; set; }
    
            [JsonProperty("automaticReplies")]
            public AutomaticReplies AutomaticReplies { get; set; }
        }
    
        public partial class AutomaticReplies
        {
            [JsonProperty("message")]
            public string Message { get; set; }
    
            [JsonProperty("messageLanguage")]
            public MessageLanguage MessageLanguage { get; set; }
    
            [JsonProperty("scheduledStartTime")]
            public ScheduledTime ScheduledStartTime { get; set; }
    
            [JsonProperty("scheduledEndTime")]
            public ScheduledTime ScheduledEndTime { get; set; }
        }
    
        public partial class MessageLanguage
        {
            [JsonProperty("locale")]
            public string Locale { get; set; }
    
            [JsonProperty("displayName")]
            public string DisplayName { get; set; }
        }
    
        public partial class ScheduledTime
        {
            [JsonProperty("dateTime")]
            public string DateTime { get; set; }
    
            [JsonProperty("timeZone")]
            public string TimeZone { get; set; }
        }
    
        public partial class EmailAddress
        {
            [JsonProperty("name")]
            public string Name { get; set; }
    
            [JsonProperty("address")]
            public string Address { get; set; }
        }
    
        public partial class RootClassNameHere
        {
            public static RootClassNameHere FromJson(string json) => JsonConvert.DeserializeObject<RootClassNameHere>(json, SomeNamespaceHere.Converter.Settings);
        }
    
        public static class Serialize
        {
            public static string ToJson(this RootClassNameHere self) => JsonConvert.SerializeObject(self, SomeNamespaceHere.Converter.Settings);
        }
    
        internal static class Converter
        {
            public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
            {
                MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
                DateParseHandling = DateParseHandling.None,
                Converters =
                {
                    new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
                },
            };
        }
    }
    
    

    (I chose "SomeNamespaceHere" and "RootClassNameHere" for the relevant names of namespace and class root; you might choose different)

    And then you use it like this (the deser step will work differently depending on the service you used):

    var rootClassNameHere = RootClassNameHere.FromJson(jsonString); //deser
    var someLinq = rootClassNameHere.Value.Select(v => v.AutomaticReplies.Message); //query