2017-02-01 1 views
1

Ich habe die Bibliotheken Newtonsoft.Json und Newtonsoft.Json.Fsharp verwendet, um einen neuen JSON Serializer zu erstellen und in eine Datei zu streamen. Ich mag die Fähigkeit, zu einer Datei zu streamen, weil ich große Dateien behandle und vor dem Streamen häufig Speicherprobleme hatte.Verwenden von Microsoft.FSharpLu zum Serialisieren von JSON in einem Stream

ich streamen mit einem einfachen fx:

open Newtonsoft.Json 
open Newtonsoft.Json.FSharp 
open System.IO 

let writeToJson (path: string) (obj: 'a) : unit = 
    let serialized = JsonConvert.SerializeObject(obj) 
    let fileStream = new StreamWriter(path) 
    let serializer = new JsonSerializer() 

    serializer.Serialize(fileStream, obj) 

    fileStream.Close() 

Dies funktioniert gut. Mein Problem ist, dass die JSON Zeichenfolge dann mit Dingen vollgestopft ist, die ich nicht brauche. Zum Beispiel

let m = 
    [ 
     (1.0M, None) 
     (2.0M, Some 3.0M) 
     (4.0M, None) 
    ] 

let makeType (tup: decimal * decimal option) = {FieldA = fst tup; FieldB = snd tup} 

let y = List.map makeType m 

Default.serialize y 

val it : string = 
    "[{"FieldA": 1.0}, 
    {"FieldA": 2.0, 
    "FieldB": { 
     "Case": "Some", 
     "Fields": [3.0] 
    }}, 
    {"FieldA": 4.0}]" 

Wenn dies zu einer JSON geschrieben und gelesen in R gibt es Datenrahmen verschachtelt und mit einer der Fields in Verbindung mit einem Case Ende bis ein list sein:

library(jsonlite) 
library(dplyr) 

q <- fromJSON("default.json") 

x <- 
    q %>% 
    flatten() 

x 

> x 
    FieldA FieldB.Case FieldB.Fields 
1  1  <NA>   NULL 
2  2  Some    3 
3  4  <NA>   NULL 
> sapply(x, class) 
     FieldA FieldB.Case FieldB.Fields 
    "numeric" "character"  "list" 

I don Ich möchte mit diesen Dingen in R umgehen müssen. Ich kann es tun, aber es ist nervig und wenn es Dateien mit vielen, vielen Spalten gibt, ist es albern.

Heute Morgen begann ich, die Microsoft.FSharpLu.Json documentation zu betrachten. Diese Bibliothek hat eine Compact.serialize Funktion. Schnelltests schlagen vor, dass diese Bibliothek die Notwendigkeit verschachtelter Datenrahmen und der list s, die mit irgendwelchen Case und Field Spalten verbunden sind, beseitigt. Zum Beispiel:

Compact.serialize y 

val it : string = 
    "[{ 
    "FieldA": 1.0 
    }, 
    { 
    "FieldA": 2.0, 
    "FieldB": 3.0 
    }, 
    { 
    "FieldA": 4.0 
    } 
    ]" 

Wenn diese Zeichenfolge in R gelesen wird,

q <- fromJSON("compact.json") 

x <- q 
x 
> x 
    FieldA FieldB 
1  1  NA 
2  2  3 
3  4  NA 
> sapply(x, class) 
    FieldA FieldB 
"numeric" "numeric 

Das ist viel einfacher in R. zu handhaben, und ich möchte mit dieser Bibliothek starten.

Allerdings weiß ich nicht, ob ich den Serializer Compact Serialisierung zu einem Stream erhalten kann. Ich sehe .serializeToFile, .desrializeStream und .tryDeserializeStream, aber nichts, das zu einem Strom serialisieren kann. Weiß jemand, ob Compact Schreibzugriff auf einen Stream verarbeiten kann? Wie kann ich das machen?

+1

"Sachen, die Sie nicht brauchen"? –

+1

@FyodorSoikin Ja, eine alberne Phrase, aber sieh dir den Unterschied zwischen der Ausgabe von 'Default.serialize' und' Compact.serialize' in der ['Microsoft.FSharpLu.Json' Bibliothek] an (https://github.com/ Microsoft/fsharplu/wiki/fsharplu.json). Wenn ich Standard-'JSON'-Strings in' R' einlese, gibt es '2 * n'-Felder für jedes Feld, das ein' Option'-Typ ist. Mit der 'Compact'-Serialisierung verschwinden diese zusätzlichen Felder. – Steven

+1

Ich kann den Unterschied nicht "sehen", weil ich diese Bibliotheken nicht installiert habe und nicht genügend Zeit habe, einen Testplatz einzurichten. Indem Sie Ihre Frage auf diese Weise formulieren, reduzieren Sie die Anzahl potenzieller Befragter erheblich auf diejenigen, die entweder bereits genau dieses Setup haben oder zu viel Freizeit haben. –

Antwort

2

Der Helfer zur Serialisierung von dem Compact Modul in FSharpLu.Json fehlt zu streamen, aber man sollte es tun können, indem Sie das C# Beispiel von http://www.newtonsoft.com/json/help/html/SerializingJSON.htm. Etwas in die Richtung:

let writeToJson (path: string) (obj: 'a) : unit = 
    let serializer = new JsonSerializer() 
    serializer.Converters.Add(new Microsoft.FSharpLu.Json.CompactUnionJsonConverter()) 
    use sw = new StreamWriter(path) 
    use writer = new JsonTextWriter(sw) 
    serializer.Serialize(writer, obj) 
Verwandte Themen