LoginSignup
11
14

More than 5 years have passed since last update.

C#でWebAPIを使ってJSONの取得→デシリアライズ→出力

Last updated at Posted at 2018-06-02

練習と備忘録をかねてUpします。初心者向けな内容です。
WeatherHackClassはTaskを使ってAPI取得をしているので、非同期で実装する場合の参考にもなるかなと思います。

★参考★
http://www.baku-dreameater.net/archives/8741
https://gist.github.com/guitarrapc/2975aa101efa13da0caa#file-weatherhacksclass-cs-L17
http://komaken.me/blog/2013/10/17/c%E3%81%AElinq%E3%81%A7json%E3%82%92%E7%B7%A8%E9%9B%86%E3%81%97%E3%81%A6%E3%81%BF%E3%82%8B/
ありがとうございます!!


using System;
using System.Linq;
using System.Threading.Tasks;

using System.IO;
using System.Net.Http;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;

using System.Net;

namespace JsonPractice
{
    // 参考: http://www.baku-dreameater.net/archives/8741
    // 参考: https://gist.github.com/guitarrapc/2975aa101efa13da0caa#file-weatherhacksclass-cs-L17
    class Program
    {
        static void Main(string[] args)
        {
            // DeserializeObjectをもらう
            Console.WriteLine("\n-- モデルのメンバから値をとってくる ---------------\n");

            var cityCode = "130010"; //東京都のID
            var res = WeatherHacksClass.GetWeather(cityCode).Result;
            Console.WriteLine(res.pinpointLocations[0].name);



            // DesirializeObjectから、ParseしたJSONに戻す。単純に値を全部見るならこの方法のほうが楽
            Console.WriteLine("\n-- 全部列挙(生JSON→デシリアライズ→シリアライズ -----------------\n");

            var jsonDes = WeatherHacksClass.GetWeather(cityCode).Result;
            string formattedJson = JsonConvert.SerializeObject(jsonDes, Formatting.Indented);
            Console.WriteLine(formattedJson);



            // JContainerをもらう  参考(コメ欄):https://teratail.com/questions/50952  
            // けどこれもらった後の扱いが微妙。クラス作ってDeserializeObjectでもらうほうが扱いやすい気がする
            Console.WriteLine("\n-- 全部列挙(生JSON→JContainer) -----------------\n");

            var retContainer = WeatherHacksClass3.GetWeather(cityCode).Result;
            var values = retContainer.DescendantsAndSelf()
                .OfType<JProperty>()
                .Select(p => p.Name + ": " + p.Value) // 「task_id: 10」という風になる
                .ToArray();

            foreach (var value in values)
            {
                Console.WriteLine(value.ToString());
            }




            // 参考: https://netweblog.wordpress.com/2016/10/24/json-net-newtonsoft-json-usage/
            // 例えば、いっこだけパラメータ取り出したい場合はこんな感じ。
            Console.WriteLine("\n-- 値取り出し(JContainer) ---------------------\n");
            var tmpArray = (JArray)retContainer["forecasts"];   // メンバ変数で指定できないのはうーん..って感じか
            foreach (JObject jobj in tmpArray)
            {
                JValue telopValue = (JValue)jobj["telop"];
                string telop = (string)telopValue.Value;
                JValue dateLabelValue = (JValue)jobj["dateLabel"];
                string dateLabel = (string)dateLabelValue.Value;
                Console.WriteLine($"name is {dateLabel}, price is {telop}.");
            }



            // LINQを使ってみる  参考: http://komaken.me/blog/2013/10/17/c%E3%81%AElinq%E3%81%A7json%E3%82%92%E7%B7%A8%E9%9B%86%E3%81%97%E3%81%A6%E3%81%BF%E3%82%8B/
            Console.WriteLine("\n-- 値取り出し(生JSON→jObject(モデルを作らない) ----------------\n");

            String url = "http://express.heartrails.com/api/json?method=getStations&line=JR%E5%B1%B1%E6%89%8B%E7%B7%9A";
            WebRequest request = WebRequest.Create(url);
            Stream response_stream = request.GetResponse().GetResponseStream();
            StreamReader reader = new StreamReader(response_stream);

            //Console.WriteLine(reader.ReadToEnd());
            var obj_from_json = JObject.Parse(reader.ReadToEnd());

            var search_result = from foo in obj_from_json["response"]["station"]
                                where ((String)foo["name"]).Contains("町")
                                select foo;     // 町を含む駅名を表示

            foreach (var r in search_result)
            {
                Console.WriteLine(r["name"]);
            }


            Console.WriteLine("\n-- 値取り出し(生JSON→jObject(モデルを作らない) ----------------\n");

            search_result = from foo in obj_from_json["response"]["station"] select foo;  //全部表示

            foreach (var r in search_result)
            {
                Console.WriteLine(r["name"]);
            }

            Console.WriteLine("Press any key to finish.");
            Console.Read();
        }
    }



    //JContainerを返す
    public class WeatherHacksClass3
    {
        private const string baseUrl = "http://weather.livedoor.com/forecast/webservice/json/v1";

        public static async Task<JContainer> GetWeather(string cityCode)
        {
            var url = $"{baseUrl}?city={cityCode}";
            var result = await new HttpClient().GetAsync(url, HttpCompletionOption.ResponseHeadersRead);
            var jsonString = await result.Content.ReadAsStringAsync();
            var root = (JContainer)JToken.Parse(jsonString);
            return root;
        }
    }


    //文字列をそのまま返す
    public class WeatherHacksClass2
    {
        private const string baseUrl = "http://weather.livedoor.com/forecast/webservice/json/v1";

        public static async Task<string> GetWeather(string cityCode)
        {
            var url = $"{baseUrl}?city={cityCode}";
            var result = await new HttpClient().GetAsync(url, HttpCompletionOption.ResponseHeadersRead);
            var jsonString = await result.Content.ReadAsStringAsync();
            return jsonString;
        }
    }


    // シリアライズしたオブジェクトを返す
    public class WeatherHacksClass
    {
        private const string baseUrl = "http://weather.livedoor.com/forecast/webservice/json/v1";

        public static async Task<WeatherResponse> GetWeather(string cityCode)
        {
            var url = $"{baseUrl}?city={cityCode}";
            var result = await new HttpClient().GetAsync(url, HttpCompletionOption.ResponseHeadersRead);
            var jsonString = await result.Content.ReadAsStringAsync();
            var response = JsonConvert.DeserializeObject<WeatherResponse>(jsonString);
            return response;
        }
    }

    // ここから下は受け取るJsonのデータ型を定義しているよ -----------------------
    public class WeatherResponse
    {
        public Pinpointlocation[] pinpointLocations { get; set; }
        public string link { get; set; }
        public Forecast[] forecasts { get; set; }
        public Location location { get; set; }
        public DateTime publicTime { get; set; }
        public Copyright copyright { get; set; }
        public string title { get; set; }
        public Description description { get; set; }

    }

    public class Location
    {
        public string city { get; set; }
        public string area { get; set; }
        public string prefecture { get; set; }
    }

    public class Copyright
    {
        public Provider[] provider { get; set; }
        public string link { get; set; }
        public string title { get; set; }
        public Image image { get; set; }
    }

    public class Image
    {
        public int width { get; set; }
        public string link { get; set; }
        public string url { get; set; }
        public string title { get; set; }
        public int height { get; set; }
    }

    public class Provider
    {
        public string link { get; set; }
        public string name { get; set; }
    }

    public class Description
    {
        public string text { get; set; }
        public DateTime publicTime { get; set; }
    }

    public class Pinpointlocation
    {
        public string link { get; set; }
        public string name { get; set; }
    }

    public class Forecast
    {
        public string dateLabel { get; set; }
        public string telop { get; set; }
        public string date { get; set; }
        public Temperature temperature { get; set; }
        public Image1 image { get; set; }
    }

    public class Temperature
    {
        public Min min { get; set; }
        public Max max { get; set; }
    }

    public class Min
    {
        public string celsius { get; set; }
        public string fahrenheit { get; set; }
    }

    public class Max
    {
        public string celsius { get; set; }
        public string fahrenheit { get; set; }
    }

    public class Image1
    {
        public int width { get; set; }
        public string url { get; set; }
        public string title { get; set; }
        public int height { get; set; }
    }

}

2018.06.05追記
値を全部出力するときSerealizeObjectを使う方法を追記しました。

11
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
14