2010-11-01 8 views
15

Provengo da una terra dotnet, ma recentemente ho esaminato le possibilità di linguaggi di programmazione alternativi. Niente di veramente serio, solo alcuni pezzi qua e là. Recentemente ho scoperto Scala e ne sono abbastanza affascinato. Nonostante il bricolage non deterministico, ho fatto alcuni controlli intermedi su cose che sono importanti per me in C# e mi sento piuttosto soddisfatto: nozioni funzionali - tick, polimorfismo ad-hoc - tick, annotazioni - tick, reflection e codegen - tick.Elaborazione JSON senza rumore con Scala

Ora sto pensando a come si potrebbe programmare un analogo della libreria di elaborazione JSON che ho implementato in C# 4.0 con l'aiuto della DLR e dello zucchero sintattico "dinamico". Ecco il set di funzionalità che sto cercando:

  1. Navigazione comoda e costruzione di JSON raw.
  2. Conversione automatica tra JSON e oggetti/raccolte nativi (nella sua forma generale il problema è irrisolvibile, sebbene sia possibile definire convenzioni che funzionino il 95% delle volte - e per me va bene).

nuove funzionalità di C# 4.0 po roccia qui, dal momento che mi hanno lasciato a ignorare l'accesso utente e il tipo di calchi di eseguire logica completamente personalizzato (se una variabile in C# 4.0 è tipizzata come "dinamico", quindi tutto ciò che fate con esso sarà compilato in chiamate a metodi definiti dal programmatore con un comportamento predefinito ragionevole - vedi DynamicMetaObject.BindXXX methods at MSDN per maggiori informazioni). Per esempio. Ho tipo sovresposta getta per serializzare/deserializzare oggetti .NET e membro accessi per gestire JSON grezzo, in modo che io possa scrivere il seguente codice:

var json = Json.Get("http://some.service"); 
if (json.foo) Console.WriteLine((Foo)json.foo); 
json.bars = ((List<Bar>)json.bars).DoSomething(); 

Naturalmente, questo non è l'ideale, in quanto legame dinamico in C# 4.0 ha problemi con i metodi di estensione e inferenza di tipo, e, inoltre, il codice si sente ancora piuttosto pesante. Ma comunque, è molto meglio che usare tutti quelli ((JsonObject) json ["quux"]) ["baz"] che ho usato nel C# 3.5.

Alcune ricerche di base mostrano che Scala non dispone di funzioni linguistiche dedicate che supportano l'associazione tardiva. Tuttavia, ci sono così tanti trucchi che forse possono essere usati insieme per creare un'emulazione sopportabile del codice mostrato sopra (o anche per essere migliori - sono quasi sicuro che questo sia possibile). Potresti, per favore, consigliarmi qualcosa qui?

risposta

15

Una libreria JSON utile per Scala è lift-json, che è un componente autonomo di Lift Web Framework.

https://github.com/lift/framework/tree/master/core/json

essa supporta l'estrazione alle classi, l'analisi e un modem DSL per la creazione di JSON.

La pagina a cui mi sono collegato ha un tutorial completo, quindi non mi limiterò a copiarlo e incollarlo.

+1

lift-JSON è grande se si esegue sul lato server ... purtroppo la sua dipendenza scalap e quindi scala-compilatore significa che può essere un grande pezzo o' byte se siete footprint- sensibile. –

6

Si dovrebbe assolutamente dare un'occhiata a sjson. Qui ->sjson on github Sto usando l'implementazione basata sulla classe Type, che puoi esaminare qui ->some examples Se hai una scappatoia attraverso il codice, ci sono alcuni trucchi scala davvero interessanti. Questo dovrebbe darti quello che stai cercando per quanto riguarda il # 2. SJSON avvolge dispatch-json che credo fornisca l'integrazione a lift-json (menzionato sopra). Sia dispatch-json/lift-json dovrebbe darti quello che stai cercando in # 1. Per quello che vale ho usato sjson in un grande progetto e il suo andare a nuoto. E il gentiluomo dietro al progetto è stato piuttosto sorprendente e sostiene il progetto molto bene.

2

Come altri hanno sottolineato, ci sono molte scelte.Oltre a quelle menzionate, la maggior parte delle librerie di elaborazione Java JSON dovrebbe funzionare anche con Scala, con vari livelli di (in) comodità per linguaggi JVM non Java (come Scala, Clojure, Groovy).

I più potenti in termini di associazione dati sono Jackson, GSON e FlexJSON. Una possibilità è di controllarli e vedere se è possibile contribuire a migliorare l'interoperabilità - Scala ad esempio ha un numero di tipi di dati "esotici" che trarrebbero vantaggio da una gestione esplicita (oltre alla gestione degli oggetti java "standard" supportati da libs)).

1

Se vuoi qualcosa di veramente dinamico in scala, eccolo: http://www.scala-lang.org/api/current/scala/Dynamic.html

A marker trait that enables dynamic invocations. Instances x of this trait allow calls x.meth(args) for arbitrary method names meth and argument lists args. If a call is not natively supported by x, it is rewritten to x.applyDynamic("meth", args). 

As of scala 2.9, scalac must receive the -Xexperimental optional for Dynamic to receive this treatment. 

Ora, si tratta di una funzione sperimentale, e non forte come il DLR .NET.

Casbah il driver scala-mongodb lo ha provato.

+0

I tratti dinamici sono stati rilasciati ufficialmente come parte di Scala 2.10. – clemp6r

5

ho galleggiato tra l'utilizzo lift-json e le varie varianti di sjson (ad esempio dabasishg/sjson) e più recentemente Jerkson (un wrapper Scala il Jackson).

Ai fini della serializzazione degli oggetti e deserializzazione continuo a trovare Jerkson per richiedere il minimo ritocco per ottenere un lavoro fatto, per esempio, ho appena codifica una semplice serializzazione oggetto con un case class che assomiglia a questo:

import org.joda.time.LocalDate 

case class UserStatus(subscriptionEndDate: LocalDate = null) 

ho avuto vari errori sia con lift-json e sjson ma jerkson appena lavorato con:

import com.codahale.jerkson.Json 

val jsonString = Json.generate(statusObject) 

e

val newObject = Json.parse[UserStatus](jsonString) 
0

abbastanza interestinly il codice per fare questo in scala è molto più complessa di quella di Java .. nessuna di queste risposte dare un rumore soluzione gratuita come la libreria Java Jackson tranne Jerkson che avvolge Jackson.

ObjectMapper mapper = new ObjectMapper(); // can reuse, share globally User user = mapper.readValue(new File("user.json"), User.class); //to parse mapper.writeValue(new File("user-modified.json"), user); //to produce