2014-06-27 20 views
8

Penso che il titolo di questo sia sbagliato, ma non posso creare un titolo che rifletta, in astratto, ciò che voglio ottenere.Cambiare un oggetto immutabile F #

Sto scrivendo una funzione che chiama un servizio e recupera i dati come una stringa JSON. La funzione analizza la stringa con un JSON type provider. In determinate condizioni, desidero modificare le proprietà su quell'oggetto JSON e quindi restituire la stringa dell'oggetto modificato. Quindi, se la risposta dalla chiamata era

{"property1" : "value1","property2" : "value2", "property3": "value3" } 

voglio cambiare property3 ad un nuovo valore e poi tornare la stringa JSON.

Se il JsonProvider era mutabile questo sarebbe un esercizio come:

type JsonResponse = 
     JsonProvider<""" {"property1" : "value1", 
          "property2" : "value2", 
          "property3": "value3" } """> 

let jsonResponse = JsonResponse.Parse(response) 
jsonResponse.Property3 <- "new value" 
jsonResponse.ToString() 

Tuttavia, questo non funziona in quanto la proprietà non può essere impostata. Sto cercando di accertare il modo migliore per risolvere questo problema. Sono abbastanza felice di inizializzare un nuovo oggetto basato sulla risposta originale ma con parametri modificati, ma non sono sicuro che ci sia un modo semplice per raggiungere questo obiettivo.

Per riferimento, l'oggetto JSON è molto più coinvolto rispetto all'esempio piatto fornito e contiene una gerarchia profonda.

+0

Se il tipo di 'jsonResponse' era un record, è possibile eseguire' {jsonRespose con Property3 = "nuovo valore"} '. Ma non sembra funzionare. – svick

+1

sfortunatamente, i provider di tipi non sono attualmente in grado di creare tipi di record. –

risposta

6

Sì, è necessario creare un nuovo oggetto, modificare i bit desiderati e utilizzare i valori dell'oggetto esistente per il resto. Abbiamo aggiunto API di scrittura per entrambi i provider di tipi XML e JSON un po 'di tempo fa. Noterai che i tipi che rappresentano il tuo JSON hanno costruttori su di essi. È possibile vedere un esempio di questo in uso nella parte inferiore di this link

+2

Grazie per questa risposta. Ho sperimentato questo e l'unico modo in cui posso farlo è specificando tutte le proprietà del JSON come argomenti nel costruttore. Questo funziona per l'esempio che ho dato let newThing = JsonResponse.Example ("value2", "value3", "value3") ma per un grafo di oggetti di grandi dimensioni questo non è veramente pratico. Hai qualche idea su come potresti farlo in un modo più "schizzinoso", cioè solo modificando le proprietà specifiche del vecchio oggetto nel nuovo oggetto. Le proprietà che voglio impostare sul nuovo oggetto sono un paio di livelli profondi all'interno della gerarchia. – AlexC

+1

Le API di scrittura sono relativamente nuove, abbiamo aggiunto il supporto completo del costruttore e la possibilità di copiare da altri oggetti JsonValue (il tipo sottostante cancellato): questo consente di copiare i dati tra tipi di provider JSON che condividono sottotipi identici all'interno di loro. Per quello che vuoi, probabilmente avrebbe bisogno di un nuovo supporto nel provider di tipi. Sono d'accordo che sarebbe utile, dovresti forse aprire un problema nel github di FSharp.Data per questo. (o provalo tu stesso!) –

+0

Apparentemente non è attualmente possibile: https://github.com/fsharp/FSharp.Data/issues/914#issuecomment-189069108 – Jon49

Problemi correlati