2017-03-19 14 views
2

OK、私は短く具体的にしようとします。私は私は、関連するコードを貼り付けますの下に、これまでのところ(それの短いバージョン、唯一の2つのサンプルを取った)とても良いJSON文字列をC#クラスにデシリアライズ

[{ 
    "$type": "Tfl.Api.Presentation.Entities.Line, Tfl.Api.Presentation.Entities", 
    "id": "bakerloo", 
    "name": "Bakerloo", 
    "modeName": "tube", 
    "disruptions": [], 
    "created": "2017-03-16T15:56:01.01Z", 
    "modified": "2017-03-16T15:56:01.01Z", 
    "lineStatuses": [ 
     { 
     "$type": "Tfl.Api.Presentation.Entities.LineStatus, Tfl.Api.Presentation.Entities", 
     "id": 0, 
     "statusSeverity": 10, 
     "statusSeverityDescription": "Good Service", 
     "created": "0001-01-01T00:00:00", 
     "validityPeriods": [] 
     } 
    ], 
    "routeSections": [], 
    "serviceTypes": [ 
     { 
     "$type": "Tfl.Api.Presentation.Entities.LineServiceTypeInfo, Tfl.Api.Presentation.Entities", 
     "name": "Regular", 
     "uri": "/Line/Route?ids=Bakerloo&serviceTypes=Regular" 
     } 
    ], 
    "crowding": { 
     "$type": "Tfl.Api.Presentation.Entities.Crowding, Tfl.Api.Presentation.Entities" 
    } 
    }, 
    { 
    "$type": "Tfl.Api.Presentation.Entities.Line, Tfl.Api.Presentation.Entities", 
    "id": "central", 
    "name": "Central", 
    "modeName": "tube", 
    "disruptions": [], 
    "created": "2017-03-16T15:56:01.01Z", 
    "modified": "2017-03-16T15:56:01.01Z", 
    "lineStatuses": [ 
     { 
     "$type": "Tfl.Api.Presentation.Entities.LineStatus, Tfl.Api.Presentation.Entities", 
     "id": 0, 
     "statusSeverity": 10, 
     "statusSeverityDescription": "Good Service", 
     "created": "0001-01-01T00:00:00", 
     "validityPeriods": [] 
     } 
    ], 
    "routeSections": [], 
    "serviceTypes": [ 
     { 
     "$type": "Tfl.Api.Presentation.Entities.LineServiceTypeInfo, Tfl.Api.Presentation.Entities", 
     "name": "Regular", 
     "uri": "/Line/Route?ids=Central&serviceTypes=Regular" 
     }, 
     { 
     "$type": "Tfl.Api.Presentation.Entities.LineServiceTypeInfo, Tfl.Api.Presentation.Entities", 
     "name": "Night", 
     "uri": "/Line/Route?ids=Central&serviceTypes=Night" 
     } 
    ], 
    "crowding": { 
     "$type": "Tfl.Api.Presentation.Entities.Crowding, Tfl.Api.Presentation.Entities" 
    } 
    }] 

:私はこのようになりますパブリックAPIからJSON文字列を取得しています私は json2csharp無料のオンラインサービスから得たC#クラスにこのJSON文字列を逆シリアル化しようとしています。私がこれを達成しようとしている関連するコードは次のとおりです:上記のコメントを読むことができますので、返す前にデータを取得しています。

json2csharpによって生成されたクラスは次のようになります。

明らか
[DataContract] 
public class Disruption 
{ 
    [DataMember] 
    public string type { get; set; } 

    [DataMember] 
    public string category { get; set; } 

    [DataMember] 
    public string categoryDescription { get; set; } 

    [DataMember] 
    public string description { get; set; } 

    [DataMember] 
    public string additionalInfo { get; set; } 

    [DataMember] 
    public string created { get; set; } 

    [DataMember] 
    public List<object> affectedRoutes { get; set; } 

    [DataMember] 
    public List<object> affectedStops { get; set; } 

    [DataMember] 
    public string closureText { get; set; } 

    [DataMember] 
    public bool? isWholeLine { get; set; } 
} 

[DataContract] 
public class LineStatus 
{ 
    [DataMember] 
    public string type { get; set; } 

    [DataMember] 
    public int id { get; set; } 

    [DataMember] 
    public int statusSeverity { get; set; } 

    [DataMember] 
    public string statusSeverityDescription { get; set; } 

    [DataMember] 
    public string created { get; set; } 

    [DataMember] 
    public List<object> validityPeriods { get; set; } 

    [DataMember] 
    public string lineId { get; set; } 

    [DataMember] 
    public string reason { get; set; } 

    [DataMember] 
    public Disruption disruption { get; set; } 
} 

[DataContract] 
public class ServiceType 
{ 
    [DataMember] 
    public string type { get; set; } 

    [DataMember] 
    public string name { get; set; } 

    [DataMember] 
    public string uri { get; set; } 
} 

[DataContract] 
public class Crowding 
{ 
    [DataMember] 
    public string type { get; set; } 
} 

[DataContract] 
public class tubeStatusRootObject 
{ 
    [DataMember] 
    public string type { get; set; } 

    [DataMember] 
    public string id { get; set; } 

    [DataMember] 
    public string name { get; set; } 

    [DataMember] 
    public string modeName { get; set; } 

    [DataMember] 
    public List<object> disruptions { get; set; } 

    [DataMember] 
    public string created { get; set; } 

    [DataMember] 
    public string modified { get; set; } 

    [DataMember] 
    public List<LineStatus> lineStatuses { get; set; } 

    [DataMember] 
    public List<object> routeSections { get; set; } 

    [DataMember] 
    public List<ServiceType> serviceTypes { get; set; } 

    [DataMember] 
    public Crowding crowding { get; set; } 
} 

私はちょうどそこ[DataContract]さんと[DataMember]年代を追加しました。そして私が間違っているのかのアイデアをお持ちの方は、私はいくつかのnewtonsoft JSONを使用して多くの類似の質問に、見つけたとして、重複をマークしないでくださいChannel9

から例を追ってきた私に

を助けることができますそこから私の例にソリューションを実装することができませんでした

+0

は、なぜあなたはnewtonsoft使用することはできませんか? – fredrik

+0

それは私が傾けることはできません、私はちょうどリンクされた例に従って、私はそれがどのように動作するか、または私の場合、それが動作していない理由を理解したい:) – al1en

+0

あなたはnewtonsoftで動作させることはできません。巨大なdiff ... – fredrik

答えて

1

これは少し複雑なオブジェクトです。

デシリアライズされると(現在のやり方)、期待どおりに同じデータ型のオブジェクトの名前が一致するかどうかがわかります。見つからない場合、デシリアライゼーションは失敗し、nullを返します。それはかなり確かです。

newtonsoftでない場合は、各ネストされたオブジェクトのデータ型をいくつかの一般的なものに一致させることができます。または、自分で逆シリアル化するためにいくつかの文字列操作を実行する必要があります(かなり複雑です)。

私が提供されるサンプルデータが配列(tubeStatusRootObject[])を説明していますが逆シリアル化しようとすると、無効なキャストである単一のインスタンスにキャストし、そのようなオブジェクトに対して

+0

私が見ているオブジェクト全体は、https://api.tfl.gov.uk/Line/Mode/tube/Statusで見ることができますが、オブジェクト自体は毎回異なるでしょう。いくつかの中断や同様の変更に依存しますlines – al1en

2

をNewtonsoft.jsonを使用して好むだろう。だからdatanullです。

また、問題を簡単に解決できるツールがあれば、ホイールを再発明する必要もありません。他の人が言ったように

static http = new HttpClient(); //reuse httpclient instead of creating a new one each time. 
public async static Task<tubeStatusRootObject[]> GetTubeStatus(string url) { 
    var response = await http.GetAsync(url); 
    var json = await response.Content.ReadAsStringAsync(); //This is working 
    var data = Newtonsoft.Json.JsonConvert.DeserializeObject<tubeStatusRootObject[]>(json); 
    return data; 
} 
+0

私はNewtonsoft.Jsonを実装するためにコードを変更しました。私は結果を返しました。だから、Newtonsoftを実装せずに同じ結果を達成する簡単な方法はありませんか? – al1en

+2

@ al1en、確かに他の方法もありますが、自分でやることはずっと複雑です。 – Nkosi

+0

デシリアライズされたオブジェクトがあります。それがそこにあります! :D Newtonsoftでかなり簡単! –

1

は、アレイにデシリアライズする必要があり、あなたが応答として定義したタイプのだけではなく、単一のインスタンスは、配列です。

あなたは文字列に応答を読めば、その後Json.NetはあなただけDataContractJsonSerializer

var deserializer = new DataContractJsonSerializer(typeof(tubeStatusRootObject[])); 
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(result))) 
{ 
    var data = (tubeStatusRootObject[])deserializer.ReadObject(ms); 
} 

(注を使用している場合、これは3本の+ラインと比較され

var data= Newtonsoft.Json.JsonConvert.DeserializeObject<tubeStatusRootObject[]>(result); 

単一行の応答を必要とする意味MemoryStreamを確保するためにusingラッパーを使用することができます。)

HTTPレスポンスストリームをデシリアライザに直接読み込むと、LoCの保存はできません。

using (var stream = await response.Content.ReadAsStreamAsync()) 
{ 
    var dcjs = new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(tubeStatusRootObject[])); 

    var data= (tubeStatusRootObject[])dcjs.ReadObject(stream); 
} 

using (var s = http.GetStreamAsync(url).Result) 
using (var sr = new StreamReader(s)) 
using (var reader = new Newtonsoft.Json.JsonTextReader(sr)) 
{ 
    var serializer = new Newtonsoft.Json.JsonSerializer(); 
    var data = serializer.Deserialize<tubeStatusRootObject[]>(reader); 
} 

あなたは検討する必要があります他の事は、パフォーマンスです。 Json.Net claim the following

Json Serializers performance comparison graph

関連する問題