Skip to content

Commit

Permalink
Merge pull request #96 from fslaborg/json
Browse files Browse the repository at this point in the history
Index-less json parsing
  • Loading branch information
HLWeil authored Jun 28, 2024
2 parents d16c143 + 302d69a commit ecd768c
Show file tree
Hide file tree
Showing 15 changed files with 504 additions and 97 deletions.
16 changes: 8 additions & 8 deletions src/FsSpreadsheet.Js/FsExtensions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ type FsWorkbook with
static member fromRowsJsonString (json:string) : FsWorkbook =
Json.fromRowsJsonString json

static member toRowsJsonString (wb:FsWorkbook) : string =
Json.toRowsJsonString wb
static member toRowsJsonString (wb:FsWorkbook,?spaces, ?noNumbering) : string =
Json.toRowsJsonString(wb, ?spaces = spaces, ?noNumbering = noNumbering)

//static member fromJsonFile (path:string) : Promise<FsWorkbook> =
// Json.fromJsonFile path
Expand All @@ -55,15 +55,15 @@ type FsWorkbook with
//member this.ToJsonFile(path: string) : Promise<unit> =
// FsWorkbook.toJsonFile path this

member this.ToRowsJsonString() : string =
FsWorkbook.toRowsJsonString this
member this.ToRowsJsonString(?spaces, ?noNumbering) : string =
FsWorkbook.toRowsJsonString(this, ?spaces = spaces, ?noNumbering = noNumbering)


static member fromColumnsJsonString (json:string) : FsWorkbook =
Json.fromColumnsJsonString json

static member toColumnsJsonString (wb:FsWorkbook) : string =
Json.toColumnsJsonString wb
static member toColumnsJsonString (wb:FsWorkbook,?spaces, ?noNumbering) : string =
Json.toColumnsJsonString(wb, ?spaces = spaces, ?noNumbering = noNumbering)

member this.ToColumnsJsonString() : string =
FsWorkbook.toColumnsJsonString this
member this.ToColumnsJsonString(?spaces, ?noNumbering) : string =
FsWorkbook.toColumnsJsonString(this, ?spaces = spaces, ?noNumbering = noNumbering)
10 changes: 6 additions & 4 deletions src/FsSpreadsheet.Js/Json.fs
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,10 @@ type Json =
| Ok wb -> wb
| Error e -> failwithf "Could not deserialize json Workbook: \n%s" e

static member toRowsJsonString (wb:FsWorkbook, ?spaces) : string =
static member toRowsJsonString (wb:FsWorkbook, ?spaces, ?noNumbering) : string =
let spaces = defaultArg spaces 2
FsSpreadsheet.Json.Workbook.encodeRows wb
let noNumbering = defaultArg noNumbering false
FsSpreadsheet.Json.Workbook.encodeRows noNumbering wb
|> Thoth.Json.JavaScript.Encode.toString spaces

static member tryFromColumnsJsonString (json:string) : Result<FsWorkbook, string> =
Expand All @@ -41,9 +42,10 @@ type Json =
| Ok wb -> wb
| Error e -> failwithf "Could not deserialize json Workbook: \n%s" e

static member toColumnsJsonString (wb:FsWorkbook, ?spaces) : string =
static member toColumnsJsonString (wb:FsWorkbook, ?spaces, ?noNumbering) : string =
let spaces = defaultArg spaces 2
FsSpreadsheet.Json.Workbook.encodeColumns wb
let noNumbering = defaultArg noNumbering false
FsSpreadsheet.Json.Workbook.encodeColumns noNumbering wb
|> Thoth.Json.JavaScript.Encode.toString spaces

//static member fromJsonFile (path:string) : Promise<FsWorkbook> =
Expand Down
57 changes: 18 additions & 39 deletions src/FsSpreadsheet.Net/FsExtensions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -319,14 +319,6 @@ module FsExtensions =
let bytes = File.ReadAllBytes filePath
FsWorkbook.fromXlsxBytes bytes

/// <summary>
/// Takes the path to an Xlsx file and returns the FsWorkbook based on its content.
/// </summary>
[<System.Obsolete("Use fromXlsxFile")>]
static member fromFile (filePath : string) =
let bytes = File.ReadAllBytes filePath
FsWorkbook.fromXlsxBytes bytes

/// <summary>
/// Takes a json string and returns the FsWorkbook based on its content.
/// </summary>
Expand Down Expand Up @@ -436,58 +428,45 @@ module FsExtensions =
self.ToXlsxBytes()
|> fun bytes -> File.WriteAllBytes (path, bytes)

/// <summary>
/// Writes the FsWorkbook into a binary file at the given path.
/// </summary>
[<System.Obsolete("Use ToXlsxFile")>]
member self.ToFile(path) =
self.ToXlsxBytes()
|> fun bytes -> File.WriteAllBytes (path, bytes)

/// <summary>
/// Writes an FsWorkbook into a binary file at the given path.
/// </summary>
static member toXlsxFile path (workbook : FsWorkbook) =
workbook.ToXlsxFile(path)

/// <summary>
/// Takes the path to an Xlsx file and returns the FsWorkbook based on its content.
/// </summary>
[<System.Obsolete("Use toXlsxFile")>]
static member toFile (filePath : string) path (workbook : FsWorkbook) =
workbook.ToXlsxFile(path)

static member toRowsJsonString (workbook : FsWorkbook, ?spaces) =
static member toRowsJsonString (workbook : FsWorkbook, ?spaces, ?noNumbering) =
let spaces = defaultArg spaces 2
FsSpreadsheet.Json.Workbook.encodeRows workbook
let noNumbering = defaultArg noNumbering false
FsSpreadsheet.Json.Workbook.encodeRows noNumbering workbook
|> Thoth.Json.Newtonsoft.Encode.toString spaces

static member toRowsJsonFile (path, ?spaces) =
static member toRowsJsonFile (path, ?spaces, ?noNumbering) =
fun workbook ->
let json = FsWorkbook.toRowsJsonString (workbook,?spaces = spaces)
let json = FsWorkbook.toRowsJsonString (workbook,?spaces = spaces, ?noNumbering = noNumbering)
File.WriteAllText(path,json)

member this.ToRowsJsonString(?spaces) =
FsWorkbook.toRowsJsonString(this, ?spaces = spaces)
member this.ToRowsJsonString(?spaces, ?noNumbering) =
FsWorkbook.toRowsJsonString(this, ?spaces = spaces, ?noNumbering = noNumbering)

member this.ToRowsJsonFile(path: string, ?spaces) =
FsWorkbook.toRowsJsonFile(path, ?spaces = spaces) this
member this.ToRowsJsonFile(path: string, ?spaces, ?noNumbering) =
FsWorkbook.toRowsJsonFile(path, ?spaces = spaces, ?noNumbering = noNumbering) this

static member toColumnsJsonString (workbook : FsWorkbook, ?spaces) =
static member toColumnsJsonString (workbook : FsWorkbook, ?spaces, ?noNumbering) =
let noNumbering = defaultArg noNumbering false
let spaces = defaultArg spaces 2
FsSpreadsheet.Json.Workbook.encodeColumns workbook
FsSpreadsheet.Json.Workbook.encodeColumns noNumbering workbook
|> Thoth.Json.Newtonsoft.Encode.toString spaces

static member toColumnsJsonFile (path, ?spaces) =
static member toColumnsJsonFile (path, ?spaces, ?noNumbering) =
fun workbook ->
let json = FsWorkbook.toColumnsJsonString (workbook,?spaces = spaces)
let json = FsWorkbook.toColumnsJsonString (workbook,?spaces = spaces, ?noNumbering = noNumbering)
File.WriteAllText(path,json)

member this.ToColumnsJsonString(?spaces) =
FsWorkbook.toColumnsJsonString(this, ?spaces = spaces)
member this.ToColumnsJsonString(?spaces, ?noNumbering) =
FsWorkbook.toColumnsJsonString(this, ?spaces = spaces, ?noNumbering = noNumbering)

member this.ToColumnsJsonFile(path: string, ?spaces) =
FsWorkbook.toColumnsJsonFile(path, ?spaces = spaces) this
member this.ToColumnsJsonFile(path: string, ?spaces, ?noNumbering) =
FsWorkbook.toColumnsJsonFile(path, ?spaces = spaces, ?noNumbering = noNumbering) this

type Writer =

Expand Down
16 changes: 8 additions & 8 deletions src/FsSpreadsheet.Py/FsExtension.fs
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ type FsWorkbook with
static member fromRowsJsonString (json:string) : FsWorkbook =
Json.fromRowsJsonString json

static member toRowsJsonString (wb:FsWorkbook) : string =
Json.toRowsJsonString wb
static member toRowsJsonString (wb:FsWorkbook,?spaces,?noNumbering) : string =
Json.toRowsJsonString(wb, ?spaces = spaces, ?noNumbering = noNumbering)

//static member fromJsonFile (path:string) : Promise<FsWorkbook> =
// Json.fromJsonFile path
Expand All @@ -51,15 +51,15 @@ type FsWorkbook with
//member this.ToJsonFile(path: string) : Promise<unit> =
// FsWorkbook.toJsonFile path this

member this.ToRowsJsonString() : string =
FsWorkbook.toRowsJsonString this
member this.ToRowsJsonString(?spaces,?noNumbering) : string =
FsWorkbook.toRowsJsonString(this, ?spaces = spaces, ?noNumbering = noNumbering)

static member fromColumnsJsonString (json:string) : FsWorkbook =
Json.fromColumnsJsonString json

static member toColumnsJsonString (wb:FsWorkbook) : string =
Json.toColumnsJsonString wb
static member toColumnsJsonString (wb:FsWorkbook,?spaces,?noNumbering) : string =
Json.toColumnsJsonString(wb, ?spaces = spaces, ?noNumbering = noNumbering)

member this.ToColumnsJsonString() : string =
FsWorkbook.toColumnsJsonString this
member this.ToColumnsJsonString(?spaces,?noNumbering) : string =
FsWorkbook.toColumnsJsonString(this, ?spaces = spaces, ?noNumbering = noNumbering)

10 changes: 6 additions & 4 deletions src/FsSpreadsheet.Py/Json.fs
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@ type Json =
| Ok wb -> wb
| Error e -> failwithf "Could not deserialize json Workbook: \n%s" e

static member toRowsJsonString (wb:FsWorkbook, ?spaces) : string =
static member toRowsJsonString (wb:FsWorkbook, ?spaces, ?noNumbering) : string =
let noNumbering = defaultArg noNumbering false
let spaces = defaultArg spaces 2
FsSpreadsheet.Json.Workbook.encodeRows wb
FsSpreadsheet.Json.Workbook.encodeRows noNumbering wb
|> Encode.toString spaces

static member tryFromColumnsJsonString (json:string) : Result<FsWorkbook, string> =
Expand All @@ -36,7 +37,8 @@ type Json =
| Ok wb -> wb
| Error e -> failwithf "Could not deserialize json Workbook: \n%s" e

static member toColumnsJsonString (wb:FsWorkbook, ?spaces) : string =
static member toColumnsJsonString (wb:FsWorkbook, ?spaces, ?noNumbering) : string =
let spaces = defaultArg spaces 2
FsSpreadsheet.Json.Workbook.encodeColumns wb
let noNumbering = defaultArg noNumbering false
FsSpreadsheet.Json.Workbook.encodeColumns noNumbering wb
|> Encode.toString spaces
4 changes: 4 additions & 0 deletions src/FsSpreadsheet/FsWorksheet.fs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ type FsWorksheet (name, ?fsRows, ?fsTables, ?fsCellsCollection) =
FsColumn(newRange,self.CellCollection)
)

member this.MaxRowIndex = this.CellCollection.MaxRowNumber

member this.MaxColumnIndex = this.CellCollection.MaxColumnNumber

// -------
// METHODS
// -------
Expand Down
11 changes: 8 additions & 3 deletions src/FsSpreadsheet/Json/Cell.fs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ let row = "row"
[<Literal>]
let value = "value"

let encodeNoNumber (cell:FsCell) =
Encode.object [
value, Value.encode cell.Value
]

let encodeRows (cell:FsCell) =
Encode.object [
column, Encode.int cell.ColumnNumber
Expand All @@ -34,7 +39,7 @@ let encodeCols (cell:FsCell) =

let decodeCols colNumber : Decoder<FsCell> =
Decode.object (fun builder ->
let v,dt = builder.Required.Field value (Value.decode)
let r = builder.Required.Field row Decode.int
new FsCell(v,dt,FsAddress(r,colNumber))
let v,dt = builder.Optional.Field value (Value.decode) |> Option.defaultValue ("", DataType.Empty)
let r = builder.Optional.Field row Decode.int |> Option.defaultValue 0
new FsCell(v,dt,FsAddress(r,Option.defaultValue 0 colNumber))
)
11 changes: 8 additions & 3 deletions src/FsSpreadsheet/Json/Column.fs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,14 @@ let encode (col:FsColumn) =
cells, Encode.seq (col.Cells |> Seq.map Cell.encodeCols)
]

let decode : Decoder<int*FsCell seq> =
let encodeNoNumbers (col: FsCell seq) =
Encode.object [
cells, Encode.seq (col |> Seq.map Cell.encodeNoNumber)
]

let decode : Decoder<int option*FsCell seq> =
Decode.object (fun builder ->
let n = builder.Required.Field number Decode.int
let cs = builder.Required.Field cells (Decode.seq (Cell.decodeCols n))
let n = builder.Optional.Field number Decode.int
let cs = builder.Optional.Field cells (Decode.seq (Cell.decodeCols n)) |> Option.defaultValue Seq.empty
n,cs
)
5 changes: 5 additions & 0 deletions src/FsSpreadsheet/Json/Row.fs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ let encode (row:FsRow) =
cells, Encode.seq (row.Cells |> Seq.map Cell.encodeRows)
]

let encodeNoNumbers (row: FsCell seq) =
Encode.object [
cells, Encode.seq (row |> Seq.map Cell.encodeNoNumber)
]

let decode : Decoder<int option*FsCell seq> =
Decode.object (fun builder ->
let n = builder.Optional.Field number Decode.int
Expand Down
8 changes: 4 additions & 4 deletions src/FsSpreadsheet/Json/Workbook.fs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ open Thoth.Json.Core
[<Literal>]
let sheets = "sheets"

let encodeRows (wb:FsWorkbook) =
let encodeRows noNumbering (wb:FsWorkbook) =
Encode.object [
sheets, Encode.seq (wb.GetWorksheets() |> Seq.map Worksheet.encodeRows)
sheets, Encode.seq (wb.GetWorksheets() |> Seq.map (Worksheet.encodeRows noNumbering))
]

let decodeRows : Decoder<FsWorkbook> =
Expand All @@ -19,9 +19,9 @@ let decodeRows : Decoder<FsWorkbook> =
wb
)

let encodeColumns (wb:FsWorkbook) =
let encodeColumns noNumbering (wb:FsWorkbook) =
Encode.object [
sheets, Encode.seq (wb.GetWorksheets() |> Seq.map Worksheet.encodeColumns)
sheets, Encode.seq (wb.GetWorksheets() |> Seq.map (Worksheet.encodeColumns noNumbering))
]

let decodeColumns : Decoder<FsWorkbook> =
Expand Down
60 changes: 54 additions & 6 deletions src/FsSpreadsheet/Json/Worksheet.fs
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,31 @@ let columns = "columns"
[<Literal>]
let tables = "tables"

let encodeRows (sheet:FsWorksheet) =
let encodeRows noNumbering (sheet:FsWorksheet) =

sheet.RescanRows()
let jRows =
if noNumbering then
[
for r = 1 to sheet.MaxRowIndex do
[
for c = 1 to sheet.MaxColumnIndex do
match sheet.CellCollection.TryGetCell(r,c) with
| Some cell -> cell
| None -> new FsCell("")

]
|> Row.encodeNoNumbers
]
|> Encode.seq
else
Encode.seq (sheet.Rows |> Seq.map Row.encode)

Encode.object [
name, Encode.string sheet.Name
if Seq.isEmpty sheet.Tables |> not then
tables, Encode.seq (sheet.Tables |> Seq.map Table.encode)
rows, Encode.seq (sheet.Rows |> Seq.map Row.encode)
rows, jRows

]

Expand Down Expand Up @@ -64,27 +82,57 @@ let decodeRows : Decoder<FsWorksheet> =
sheet
)

let encodeColumns (sheet:FsWorksheet) =
let encodeColumns noNumbering (sheet:FsWorksheet) =
sheet.RescanRows()

let jColumns =
if noNumbering then
[
for c = 1 to sheet.MaxColumnIndex do
[
for r = 1 to sheet.MaxRowIndex do
match sheet.CellCollection.TryGetCell(r,c) with
| Some cell -> cell
| None -> new FsCell("")

]
|> Column.encodeNoNumbers
]
|> Encode.seq
else
Encode.seq (sheet.Columns |> Seq.map Column.encode)

Encode.object [
name, Encode.string sheet.Name
if Seq.isEmpty sheet.Tables |> not then
tables, Encode.seq (sheet.Tables |> Seq.map Table.encode)
columns, Encode.seq (sheet.Columns |> Seq.map Column.encode)
columns, jColumns
]

let decodeColumns : Decoder<FsWorksheet> =
Decode.object (fun builder ->
let mutable colIndex = 0
let n = builder.Required.Field name Decode.string
let ts = builder.Optional.Field tables (Decode.seq Table.decode)
let cs = builder.Required.Field columns (Decode.seq Column.decode)
let sheet = new FsWorksheet(n)
cs
|> Seq.iter (fun (colI,cells) ->
let mutable rowIndex = 0
let colI =
match colI with
| Some i -> i
| None -> colIndex + 1
colIndex <- colI
let col = sheet.Column(colI)
cells
|> Seq.iter (fun cell ->
let c = col[cell.RowNumber]
|> Seq.iter (fun cell ->
let rowI =
match cell.RowNumber with
| 0 -> rowIndex + 1
| i -> i
rowIndex <- rowI
let c = col[rowIndex]
c.Value <- cell.Value
c.DataType <- cell.DataType
)
Expand Down
Loading

0 comments on commit ecd768c

Please sign in to comment.