2013-04-02 24 views
10

Attualmente sto lavorando su un proof-of-concept e ho incontrato un problema che riguarda l'uso di JSON per serializzare HttpRequest.Serializzare un oggetto di richiesta usando JSON

Sfondo

Ho inizialmente pensato che sarei stato in grado di realizzare facilmente con il metodo JSON.Encode() come si vede qui sotto:

JSON.Encode(HttpContext.Request) 

Tuttavia, ho subito scoperto che questo fa sì che tutti i tipi di circolare riferimenti da gettare (principalmente a causa della struttura e della complessità attuali dell'oggetto Richiesta). Questi si verificano solo quando effettivamente incontrando proprietà che contengono un riferimento circolare, come ho precedentemente utilizzato il seguente codice per afferrare gli elementi appena specifici che ho bisogno:

JSON.Encode(new {HttpContext.Request.Cookies,HttpContext.Request.Headers, ... }); 

che funziona bene.

Sono curioso di sapere se esiste un metodo migliore per gestirlo (o quale metodo migliore per gestirlo potrebbe essere). Descriverò in dettaglio alcuni degli approcci che ho seguito finora per trovare eventuali aree in cui potrei aver sbagliato.

precedente Approcci

  • utilizzando la riflessione per scorrere ciascuna delle proprietà all'interno del richiesta e il tentativo di costruire una stringa JSON "proprietà-by-proprietà". (Questo fallì quando incontra una circolare riferimento)

  • Cercando di memorizzare ciascuna delle proprietà di un oggetto Dictionary e quindi utilizzando JSON per serializzare l'intera Dictionary (nella speranza che sarebbe "appiattire" l'oggetto out e rendere più facile serializzare)

  • Uso della JSON.NET library e cercando di serializzare attraverso il JsonConvert.SerializeObject() metodo (ho tentato di passare in diverse impostazioni aggiuntive per evitare un riferimento circolare, ma non hanno avuto fortuna)

Il mio ultimo approccio (utilizzando la libreria JSON.NET) ho pensato che sarebbe venuto vicino a lavorare, però ho rilevato un errore che ha coinvolto una proprietà "Timeout" in funzione gli oggetti all'interno della richiesta.

Non sono contrario a evitare semplicemente la serializzazione di oggetti flusso e riferimenti circolari. Sto solo cercando di afferrare il maggior numero possibile di oggetti Request evitando qualsiasi di questi tipi di contrattempi.

risposta

3

Qualsiasi motivo particolare per cui non si utilizza JSON.Net? Ha un'impostazione chiamata PreserveReferencesHandling, che contrassegna gli oggetti con una proprietà aggiuntiva ("$ id": "##"). Se quell'oggetto appare nella serializzazione più di una volta, invece di scrivere di nuovo l'oggetto lo sostituisce con "$ ref": "##" che punta al json già esistente per l'oggetto. Ciò aggira il riferimento circolare.

Non ho mai provato a restituire JSON in quel formato a una chiamata $ .ajax, quindi non so cosa sarebbe coinvolto nell'analisi del lato web.

+0

Grazie per il suggerimento Malcolm. Ho provato ad usarlo in modi diversi da quando ho letto il tuo suggerimento e ho applicato diverse impostazioni, ma sto ancora incontrando un problema che sembra (principalmente relativo agli Stream?) "Gli stream non sono supportati su questo stream". Qualche idea? –

+0

Questo mi fa pensare che non puoi JSON Convertire un oggetto che ha una proprietà di flusso. –

+0

Sto iniziando a inclinarmi anche in quel modo. Sembra causare un timeout durante la serializzazione di un flusso e quindi emette la risposta menzionata in precedenza. Suppongo che dovrò capire un modo per ignorare i flussi/riferimenti circolari. –

2

Nel mio progetto ho utilizzato JsonConvert.SerializeObject e funziona correttamente. Sembra che possa risolvere il tuo problema.

JsonConvert.SerializeObject(reqObject) 
2

ho solo cercato di fare la stessa cosa, ora ho riuscito ad ottenere qualcosa di serializzazione utilizzando JsonConvert con un resolver contratto di ignorare tutte le proprietà del problema - ho usato questa linea per fare la serializzazione:

string reqStr = JsonConvert.SerializeObject(context.Request, 
    Formatting.Indented, new JsonSerializerSettings { 
     ReferenceLoopHandling = ReferenceLoopHandling.Ignore, 
     ContractResolver = new IgnoreErrorPropertiesResolver() 
}); 

ed ecco il codice contratto di resolver che ho usato:

public class IgnoreErrorPropertiesResolver : DefaultContractResolver 
{ 

    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) 
    { 
     JsonProperty property = base.CreateProperty(member, memberSerialization); 

     if ({"InputStream", 
      "Filter", 
      "Length", 
      "Position", 
      "ReadTimeout", 
      "WriteTimeout", 
      "LastActivityDate", 
      "LastUpdatedDate", 
      "Session" 
     }.Contains(property.PropertyName)) { 
      property.Ignored = true; 
     } 
     return property; 
    } 
} 

Questo dovrà Newtonsoft.Json.Serialization e System.Reflection usings.

Succede che non riesco a includere l'oggetto Session dove sono, quindi questo è nel mio elenco di proprietà ignorate - ovviamente rimuovilo se puoi includerlo!

Problemi correlati