2013-02-08 11 views
5

Nell'API di YouTube, è possibile richiedere uno "partial feed".Come implementeresti una richiesta e una risposta parziali, come l'api di YouTube, usando ServiceStack?

Ciò consente allo sviluppatore dell'applicazione di personalizzare le dimensioni e la struttura dei dati restituiti, specificando quali "campi" restituire.

, ovvero GET api/person/1?fields=(id,email) restituirebbe un DTO contenente solo i campi id e email, non l'intera risposta della persona.

Come si tenta di utilizzare questo ServiceStack? C'è un modo per collegare un callback al serializzatore per controllare quali proprietà includere nell'oggetto risposta?

risposta

1

Dalla mia esperienza servicestack restituisce solo campi che contengono effettivamente dati. Se la mia esperienza è corretta, tutto quello che dovresti fare è trovare il modo migliore per architettare la richiesta in modo che richieda la restituzione di dati specifici, in questo modo si riempirebbe solo la risposta con i dati richiesti, quindi il servicestack restituirà solo tale .

+0

Ho preso in considerazione questo metodo e potrebbe essere l'unico modo possibile per farlo.Sembra che la doppia gestione cammini nell'albero delle proprietà impostando i campi che non si desidera tornare a null, perché il serializzatore sta nuovamente camminando nell'albero delle proprietà per generare la risposta json. – jmc

+1

Esiste una proprietà di configurazione per controllare se i valori null vengono restituiti o meno. 'JsConfig.IncludeNullValues' – jmc

+0

Sfortunatamente questo non funzionerà con i membri DTO con tipicità. – starteleport

0

Vedere le proprietà ServiceStack.Text.JsConfig, hanno tutti i ganci e le personalizzazioni supportano i serializzatori di testo di ServiceStack. Specificamente i ganci che consentono di deserializzazione personalizzato sono:

JsConfig<T>.DeserializeFn 
JsConfig<T>.RawDeSerializeFn 
JsConfig<T>.OnDeserializedFn 
+0

Voglio personalizzare la serializzazione, non la deserializzazione. Ho dato un'occhiata alle proprietà di JsConfig e ExcludePropertyNames è il più vicino a quello che mi serve, ma non volevo definirlo a livello di Tipo, ma su una base di richiesta. – jmc

0

Siamo stati in grado di attuare detto filtraggio aggiungendo servizio personalizzato corridore e utilizzando qualche riflessione in esso per costruire ExpandoObject con campo, indicate dalla risposta DTO. Vedi this per maggiori informazioni sui corridori di servizio.

1

L'ho implementato per un'API che restituisce solo JSON.

Per prima cosa ho creato due struct per (de) serializzare e interpretare il "campi" argomento Sintassi di query ricorsive:

  • FieldSelector, che specifica un campo e, eventualmente, i suoi figli FieldSelection racchiuso tra parentesi;
  • FieldsSelection, che è un elenco separato da virgola di FieldSelector.

Ho usato le strutture anziché le classi perché, AFAIK, non è possibile sovrascrivere la serializzazione (de) di classe da/per gli URL in ServiceStack. Con struct puoi farlo ignorando ToString (serializzatore) e fornendo un costruttore che accetta una stringa come parametro (deserializzatore).

Poi si include questo su ogni DTO richiesta, che restituisce JSON:

FieldsSelection Fields { get; set; } 

Su un costume ServiceRunner<T>.OnAfterExecute si serializzare la risposta DTO a JSON, analizzarlo con ServiceStack.Text di JsonObject e applicare la selezione campi in modo ricorsivo con un metodo come questo:

private static JsonObject Apply(this JsonObject json, FieldsSelection fieldMask) 
{ 
    IEnumerable<string> keysToRemove = json.Keys.ToList().Except(fieldMask.Keys); 

    foreach (var key in keysToRemove) 
    json.Remove(key); 

    foreach (var selector in fieldMask.Selectors.Values.Where(s => s.HasSubFieldsSelection)) 
    { 
    var field = json[selector.Field]; 
    if (field == null) 
     continue; 

    switch (field[0]) 
    { 
     case '{': 
     json[selector.Field] = Apply(json.Object(selector.Field), selector.SubFieldsSelection).ToJson(); 
     break; 
     case '[': 
     var itensArray = json.ArrayObjects(selector.Field); 
     for (int i = 0; i < itensArray.Count; i++) 
      itensArray[i] = Apply(itensArray[i], selector.SubFieldsSelection); 
     json[selector.Field] = itensArray.ToJson(); 
     break; 
     default: 
     throw new ArgumentException("Selection incompatible with object structure"); 
    } 
    } 

    return json; 
} 

Quindi si restituisce il risultato come risposta DTO. Ho anche implementato selettori di campi negativi (fields=-foo seleziona tutti i campi DTO tranne foo), ma hai un'idea.

Problemi correlati