Posso serializzare tutte le risposte da un'API in un oggetto Response generico in C #?

2

Voglio utilizzare la API Tumblr in C #. Ogni richiesta all'API restituisce un oggetto con codifica JSON con lo stesso schema generale:

{
    "meta": {
        "status": 200,
        "msg": "OK"
    },
    "response": { ... }
}

meta è sempre uguale ma response è specifico per ogni richiesta. Mi piacerebbe che tutti i miei metodi restituiscano l'equivalente C # di questo oggetto:

public class TumblrEnvelope
{
    [JsonProperty("meta")]
    public Meta Meta { get; set; }

    [JsonProperty("response")]
    ???
}

public class Meta
{
    [JsonProperty("status")]
    public int Status { get; set; }

    [JsonProperty("msg")]
    public string Message { get; set; }
}

ma non sono sicuro se sia possibile implementare la proprietà Response in modo tale da poter serializzare direttamente ogni risposta a TumblrLEnvelope .

return JsonConvert.DeserializeObject<TumblrEnvelope>(result);

Questo può essere fatto? In caso contrario, quale sarebbe il più vicino che potrei ottenere?

    
posta Lawyerson 25.01.2017 - 23:04
fonte

3 risposte

5

Se stai usando Json.Net almeno. È possibile combinare e combinare Jobjects con tipi statici come meglio credi. Nel tuo caso è semplicemente una questione di fare.

public class TumblrEnvelope
{
    [JsonProperty("meta")]
    public Meta Meta { get; set; }

    [JsonProperty("response")]
    public JObject Response { get; set; }
}

Quindi puoi assaggiare la risposta e vuoi trasformarla in un tipo statico che puoi semplicemente fare (come suggerito nei commenti di Caleth)

switch (e.Meta.Status) 
{ 
    case 200: return e.Response.ToObject<Tumblr200Response>(); 
    case 404: return e.Response.ToObject<Tumblr404Response>();
    ...
}
    
risposta data 26.01.2017 - 06:00
fonte
0

Non conosci la forma della parte response in anticipo: ad esempio, in un caso di un HTTP 403, la parte response sarà molto diversa da quella ottenuta con HTTP 200.

Pertanto, non puoi semplicemente deserializzare la risposta usando una determinata classe. Quello che puoi fare, naturalmente, è impostare la proprietà Response su dynamic , ma questo non ti avvantaggerà molto.

Tuttavia, ciò che puoi fare è una deserializzazione in due passaggi:

  1. Si inizia deserializzando la risposta JSON a un oggetto che si aspetta solo due campi: /meta/status e /meta/msg . Una volta che hai questa meta informazione, il metodo può elaborarla per controllare gli errori comuni e gestirli rispettivamente (o lanciando un'eccezione o eseguendo qualsiasi attività appropriata come richiedere le credenziali all'utente.)

  2. Una volta che hai una risposta con lo stato 200 e un messaggio "OK", esegui la seconda deserializzazione, questa volta su un oggetto completo contenente i campi previsti.

Oppure puoi farlo nella direzione opposta:

  1. Tenta di deserializzare su un oggetto completo che prevedi di ricevere quando tutto è andato a buon fine.

  2. Se fallisce, deserializza solo su un oggetto che si aspetta i due campi meta e gestisci la situazione di conseguenza.

In questo modo, ottimizzerai leggermente le prestazioni se la maggior parte delle tue risposte ha esito positivo, dal momento che deselezionerai quelle risposte una sola volta.

    
risposta data 25.01.2017 - 23:39
fonte
0

In realtà potresti deserializzare in un solo passaggio, poiché la prima cosa che dovresti fare con la risposta HTTP è controllare il suo codice di stato - e non devi analizzare alcun JSON per farlo. Una volta che sai se hai ottenuto la risposta prevista o un codice di errore, puoi analizzare il JSON nella classe corretta.

    
risposta data 26.01.2017 - 13:40
fonte

Leggi altre domande sui tag