Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Release Notes

## 8.1.0-beta

- Add `PreferOptionals` parameter to `JsonProvider` and `XmlProvider` (defaults to `true` to match existing behavior; set to `false` to use empty string or `NaN` for missing values, like the CsvProvider default) (closes #649)

## 8.0.0 - Feb 25 2026

- Add PreferFloats static parameter to CsvProvider (#1655)
Expand Down
8 changes: 4 additions & 4 deletions src/AssemblyInfo.Csv.Core.fs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ open System.Reflection
[<assembly: AssemblyTitleAttribute("FSharp.Data.Csv.Core")>]
[<assembly: AssemblyProductAttribute("FSharp.Data")>]
[<assembly: AssemblyDescriptionAttribute("Library of F# type providers and data access tools")>]
[<assembly: AssemblyVersionAttribute("8.0.0.0")>]
[<assembly: AssemblyFileVersionAttribute("8.0.0.0")>]
[<assembly: AssemblyVersionAttribute("8.1.0.0")>]
[<assembly: AssemblyFileVersionAttribute("8.1.0.0")>]
do ()

module internal AssemblyVersionInformation =
let [<Literal>] AssemblyTitle = "FSharp.Data.Csv.Core"
let [<Literal>] AssemblyProduct = "FSharp.Data"
let [<Literal>] AssemblyDescription = "Library of F# type providers and data access tools"
let [<Literal>] AssemblyVersion = "8.0.0.0"
let [<Literal>] AssemblyFileVersion = "8.0.0.0"
let [<Literal>] AssemblyVersion = "8.1.0.0"
let [<Literal>] AssemblyFileVersion = "8.1.0.0"
8 changes: 4 additions & 4 deletions src/AssemblyInfo.DesignTime.fs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ open System.Reflection
[<assembly: AssemblyTitleAttribute("FSharp.Data.DesignTime")>]
[<assembly: AssemblyProductAttribute("FSharp.Data")>]
[<assembly: AssemblyDescriptionAttribute("Library of F# type providers and data access tools")>]
[<assembly: AssemblyVersionAttribute("8.0.0.0")>]
[<assembly: AssemblyFileVersionAttribute("8.0.0.0")>]
[<assembly: AssemblyVersionAttribute("8.1.0.0")>]
[<assembly: AssemblyFileVersionAttribute("8.1.0.0")>]
do ()

module internal AssemblyVersionInformation =
let [<Literal>] AssemblyTitle = "FSharp.Data.DesignTime"
let [<Literal>] AssemblyProduct = "FSharp.Data"
let [<Literal>] AssemblyDescription = "Library of F# type providers and data access tools"
let [<Literal>] AssemblyVersion = "8.0.0.0"
let [<Literal>] AssemblyFileVersion = "8.0.0.0"
let [<Literal>] AssemblyVersion = "8.1.0.0"
let [<Literal>] AssemblyFileVersion = "8.1.0.0"
8 changes: 4 additions & 4 deletions src/AssemblyInfo.Html.Core.fs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ open System.Reflection
[<assembly: AssemblyTitleAttribute("FSharp.Data.Html.Core")>]
[<assembly: AssemblyProductAttribute("FSharp.Data")>]
[<assembly: AssemblyDescriptionAttribute("Library of F# type providers and data access tools")>]
[<assembly: AssemblyVersionAttribute("8.0.0.0")>]
[<assembly: AssemblyFileVersionAttribute("8.0.0.0")>]
[<assembly: AssemblyVersionAttribute("8.1.0.0")>]
[<assembly: AssemblyFileVersionAttribute("8.1.0.0")>]
do ()

module internal AssemblyVersionInformation =
let [<Literal>] AssemblyTitle = "FSharp.Data.Html.Core"
let [<Literal>] AssemblyProduct = "FSharp.Data"
let [<Literal>] AssemblyDescription = "Library of F# type providers and data access tools"
let [<Literal>] AssemblyVersion = "8.0.0.0"
let [<Literal>] AssemblyFileVersion = "8.0.0.0"
let [<Literal>] AssemblyVersion = "8.1.0.0"
let [<Literal>] AssemblyFileVersion = "8.1.0.0"
8 changes: 4 additions & 4 deletions src/AssemblyInfo.Http.fs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ open System.Reflection
[<assembly: AssemblyTitleAttribute("FSharp.Data.Http")>]
[<assembly: AssemblyProductAttribute("FSharp.Data")>]
[<assembly: AssemblyDescriptionAttribute("Library of F# type providers and data access tools")>]
[<assembly: AssemblyVersionAttribute("8.0.0.0")>]
[<assembly: AssemblyFileVersionAttribute("8.0.0.0")>]
[<assembly: AssemblyVersionAttribute("8.1.0.0")>]
[<assembly: AssemblyFileVersionAttribute("8.1.0.0")>]
do ()

module internal AssemblyVersionInformation =
let [<Literal>] AssemblyTitle = "FSharp.Data.Http"
let [<Literal>] AssemblyProduct = "FSharp.Data"
let [<Literal>] AssemblyDescription = "Library of F# type providers and data access tools"
let [<Literal>] AssemblyVersion = "8.0.0.0"
let [<Literal>] AssemblyFileVersion = "8.0.0.0"
let [<Literal>] AssemblyVersion = "8.1.0.0"
let [<Literal>] AssemblyFileVersion = "8.1.0.0"
8 changes: 4 additions & 4 deletions src/AssemblyInfo.Json.Core.fs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ open System.Reflection
[<assembly: AssemblyTitleAttribute("FSharp.Data.Json.Core")>]
[<assembly: AssemblyProductAttribute("FSharp.Data")>]
[<assembly: AssemblyDescriptionAttribute("Library of F# type providers and data access tools")>]
[<assembly: AssemblyVersionAttribute("8.0.0.0")>]
[<assembly: AssemblyFileVersionAttribute("8.0.0.0")>]
[<assembly: AssemblyVersionAttribute("8.1.0.0")>]
[<assembly: AssemblyFileVersionAttribute("8.1.0.0")>]
do ()

module internal AssemblyVersionInformation =
let [<Literal>] AssemblyTitle = "FSharp.Data.Json.Core"
let [<Literal>] AssemblyProduct = "FSharp.Data"
let [<Literal>] AssemblyDescription = "Library of F# type providers and data access tools"
let [<Literal>] AssemblyVersion = "8.0.0.0"
let [<Literal>] AssemblyFileVersion = "8.0.0.0"
let [<Literal>] AssemblyVersion = "8.1.0.0"
let [<Literal>] AssemblyFileVersion = "8.1.0.0"
8 changes: 4 additions & 4 deletions src/AssemblyInfo.Runtime.Utilities.fs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ open System.Reflection
[<assembly: AssemblyTitleAttribute("FSharp.Data.Runtime.Utilities")>]
[<assembly: AssemblyProductAttribute("FSharp.Data")>]
[<assembly: AssemblyDescriptionAttribute("Library of F# type providers and data access tools")>]
[<assembly: AssemblyVersionAttribute("8.0.0.0")>]
[<assembly: AssemblyFileVersionAttribute("8.0.0.0")>]
[<assembly: AssemblyVersionAttribute("8.1.0.0")>]
[<assembly: AssemblyFileVersionAttribute("8.1.0.0")>]
do ()

module internal AssemblyVersionInformation =
let [<Literal>] AssemblyTitle = "FSharp.Data.Runtime.Utilities"
let [<Literal>] AssemblyProduct = "FSharp.Data"
let [<Literal>] AssemblyDescription = "Library of F# type providers and data access tools"
let [<Literal>] AssemblyVersion = "8.0.0.0"
let [<Literal>] AssemblyFileVersion = "8.0.0.0"
let [<Literal>] AssemblyVersion = "8.1.0.0"
let [<Literal>] AssemblyFileVersion = "8.1.0.0"
8 changes: 4 additions & 4 deletions src/AssemblyInfo.WorldBank.Core.fs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ open System.Reflection
[<assembly: AssemblyTitleAttribute("FSharp.Data.WorldBank.Core")>]
[<assembly: AssemblyProductAttribute("FSharp.Data")>]
[<assembly: AssemblyDescriptionAttribute("Library of F# type providers and data access tools")>]
[<assembly: AssemblyVersionAttribute("8.0.0.0")>]
[<assembly: AssemblyFileVersionAttribute("8.0.0.0")>]
[<assembly: AssemblyVersionAttribute("8.1.0.0")>]
[<assembly: AssemblyFileVersionAttribute("8.1.0.0")>]
do ()

module internal AssemblyVersionInformation =
let [<Literal>] AssemblyTitle = "FSharp.Data.WorldBank.Core"
let [<Literal>] AssemblyProduct = "FSharp.Data"
let [<Literal>] AssemblyDescription = "Library of F# type providers and data access tools"
let [<Literal>] AssemblyVersion = "8.0.0.0"
let [<Literal>] AssemblyFileVersion = "8.0.0.0"
let [<Literal>] AssemblyVersion = "8.1.0.0"
let [<Literal>] AssemblyFileVersion = "8.1.0.0"
8 changes: 4 additions & 4 deletions src/AssemblyInfo.Xml.Core.fs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ open System.Reflection
[<assembly: AssemblyTitleAttribute("FSharp.Data.Xml.Core")>]
[<assembly: AssemblyProductAttribute("FSharp.Data")>]
[<assembly: AssemblyDescriptionAttribute("Library of F# type providers and data access tools")>]
[<assembly: AssemblyVersionAttribute("8.0.0.0")>]
[<assembly: AssemblyFileVersionAttribute("8.0.0.0")>]
[<assembly: AssemblyVersionAttribute("8.1.0.0")>]
[<assembly: AssemblyFileVersionAttribute("8.1.0.0")>]
do ()

module internal AssemblyVersionInformation =
let [<Literal>] AssemblyTitle = "FSharp.Data.Xml.Core"
let [<Literal>] AssemblyProduct = "FSharp.Data"
let [<Literal>] AssemblyDescription = "Library of F# type providers and data access tools"
let [<Literal>] AssemblyVersion = "8.0.0.0"
let [<Literal>] AssemblyFileVersion = "8.0.0.0"
let [<Literal>] AssemblyVersion = "8.1.0.0"
let [<Literal>] AssemblyFileVersion = "8.1.0.0"
8 changes: 4 additions & 4 deletions src/AssemblyInfo.fs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ open System.Reflection
[<assembly: AssemblyTitleAttribute("FSharp.Data")>]
[<assembly: AssemblyProductAttribute("FSharp.Data")>]
[<assembly: AssemblyDescriptionAttribute("Library of F# type providers and data access tools")>]
[<assembly: AssemblyVersionAttribute("8.0.0.0")>]
[<assembly: AssemblyFileVersionAttribute("8.0.0.0")>]
[<assembly: AssemblyVersionAttribute("8.1.0.0")>]
[<assembly: AssemblyFileVersionAttribute("8.1.0.0")>]
do ()

module internal AssemblyVersionInformation =
let [<Literal>] AssemblyTitle = "FSharp.Data"
let [<Literal>] AssemblyProduct = "FSharp.Data"
let [<Literal>] AssemblyDescription = "Library of F# type providers and data access tools"
let [<Literal>] AssemblyVersion = "8.0.0.0"
let [<Literal>] AssemblyFileVersion = "8.0.0.0"
let [<Literal>] AssemblyVersion = "8.1.0.0"
let [<Literal>] AssemblyFileVersion = "8.1.0.0"
17 changes: 13 additions & 4 deletions src/FSharp.Data.DesignTime/Json/JsonProvider.fs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ type public JsonProvider(cfg: TypeProviderConfig) as this =
let preferDateOnly = args.[11] :?> bool
let useOriginalNames = args.[12] :?> bool
let omitNullFields = args.[13] :?> bool
let preferOptionals = args.[14] :?> bool

let inferenceMode =
InferenceMode'.FromPublicApi(inferenceMode, inferTypesFromValues)
Expand Down Expand Up @@ -100,8 +101,14 @@ type public JsonProvider(cfg: TypeProviderConfig) as this =

samples
|> Array.map (fun sampleJson ->
JsonInference.inferType unitsOfMeasureProvider inferenceMode cultureInfo "" sampleJson)
|> Array.fold (StructuralInference.subtypeInfered false) InferedType.Top
JsonInference.inferType
unitsOfMeasureProvider
inferenceMode
cultureInfo
(not preferOptionals)
""
sampleJson)
|> Array.fold (StructuralInference.subtypeInfered (not preferOptionals)) InferedType.Top
#if NET6_0_OR_GREATER
if preferDateOnly && ProviderHelpers.runtimeSupportsNet6Types cfg.RuntimeAssembly then
rawInfered
Expand Down Expand Up @@ -170,7 +177,8 @@ type public JsonProvider(cfg: TypeProviderConfig) as this =
ProvidedStaticParameter("Schema", typeof<string>, parameterDefaultValue = "")
ProvidedStaticParameter("PreferDateOnly", typeof<bool>, parameterDefaultValue = false)
ProvidedStaticParameter("UseOriginalNames", typeof<bool>, parameterDefaultValue = false)
ProvidedStaticParameter("OmitNullFields", typeof<bool>, parameterDefaultValue = false) ]
ProvidedStaticParameter("OmitNullFields", typeof<bool>, parameterDefaultValue = false)
ProvidedStaticParameter("PreferOptionals", typeof<bool>, parameterDefaultValue = true) ]

let helpText =
"""<summary>Typed representation of a JSON document.</summary>
Expand All @@ -196,7 +204,8 @@ type public JsonProvider(cfg: TypeProviderConfig) as this =
<param name='Schema'>Location of a JSON Schema file or a string containing a JSON Schema document. When specified, Sample and SampleIsList must not be used.</param>
<param name='PreferDateOnly'>When true on .NET 6+, date-only strings (e.g. "2023-01-15") are inferred as DateOnly and time-only strings as TimeOnly. Defaults to false for backward compatibility.</param>
<param name='UseOriginalNames'>When true, JSON property names are used as-is for generated property names instead of being normalized to PascalCase. Defaults to false.</param>
<param name='OmitNullFields'>When true, optional fields with value None are omitted from the generated JSON rather than serialized as null. Defaults to false.</param>"""
<param name='OmitNullFields'>When true, optional fields with value None are omitted from the generated JSON rather than serialized as null. Defaults to false.</param>
<param name='PreferOptionals'>When set to true (default), inference will use the option type for missing or null values. When false, inference will prefer to use empty string or double.NaN for missing values where possible, matching the default CsvProvider behavior.</param>"""

do jsonProvTy.AddXmlDoc helpText
do jsonProvTy.DefineStaticParameters(parameters, buildTypes)
Expand Down
11 changes: 7 additions & 4 deletions src/FSharp.Data.DesignTime/Xml/XmlProvider.fs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ type public XmlProvider(cfg: TypeProviderConfig) as this =
let preferDateOnly = args.[10] :?> bool
let dtdProcessing = args.[11] :?> string
let useOriginalNames = args.[12] :?> bool
let preferOptionals = args.[13] :?> bool

let inferenceMode =
InferenceMode'.FromPublicApi(inferenceMode, inferTypesFromValues)
Expand Down Expand Up @@ -133,9 +134,9 @@ type public XmlProvider(cfg: TypeProviderConfig) as this =
unitsOfMeasureProvider
inferenceMode
(TextRuntime.GetCulture cultureStr)
false
(not preferOptionals)
globalInference
|> Array.fold (StructuralInference.subtypeInfered false) InferedType.Top
|> Array.fold (StructuralInference.subtypeInfered (not preferOptionals)) InferedType.Top
#if NET6_0_OR_GREATER
if preferDateOnly && ProviderHelpers.runtimeSupportsNet6Types cfg.RuntimeAssembly then
t
Expand Down Expand Up @@ -203,7 +204,8 @@ type public XmlProvider(cfg: TypeProviderConfig) as this =
)
ProvidedStaticParameter("PreferDateOnly", typeof<bool>, parameterDefaultValue = false)
ProvidedStaticParameter("DtdProcessing", typeof<string>, parameterDefaultValue = "Ignore")
ProvidedStaticParameter("UseOriginalNames", typeof<bool>, parameterDefaultValue = false) ]
ProvidedStaticParameter("UseOriginalNames", typeof<bool>, parameterDefaultValue = false)
ProvidedStaticParameter("PreferOptionals", typeof<bool>, parameterDefaultValue = true) ]

let helpText =
"""<summary>Typed representation of a XML file.</summary>
Expand All @@ -229,7 +231,8 @@ type public XmlProvider(cfg: TypeProviderConfig) as this =
</param>
<param name='PreferDateOnly'>When true on .NET 6+, date-only strings are inferred as DateOnly and time-only strings as TimeOnly. Defaults to false for backward compatibility.</param>
<param name='DtdProcessing'>Controls how DTD declarations in the XML are handled. Accepted values: "Ignore" (default, silently skips DTD processing, safe for most cases), "Prohibit" (throws on any DTD declaration), "Parse" (enables full DTD processing including entity expansion, use with caution).</param>
<param name='UseOriginalNames'>When true, XML element and attribute names are used as-is for generated property names instead of being normalized to PascalCase. Defaults to false.</param>"""
<param name='UseOriginalNames'>When true, XML element and attribute names are used as-is for generated property names instead of being normalized to PascalCase. Defaults to false.</param>
<param name='PreferOptionals'>When set to true (default), inference will use the option type for missing or absent values. When false, inference will prefer to use empty string or double.NaN for missing values where possible, matching the default CsvProvider behavior.</param>"""


do xmlProvTy.AddXmlDoc helpText
Expand Down
17 changes: 13 additions & 4 deletions src/FSharp.Data.Json.Core/JsonInference.fs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ open FSharp.Data.Runtime.StructuralInference
/// functionality is handled in `StructureInference` (most notably, by
/// `inferCollectionType` and various functions to find common subtype), so
/// here we just need to infer types of primitive JSON values.
let rec internal inferType unitsOfMeasureProvider inferenceMode cultureInfo parentName json =
let rec internal inferType unitsOfMeasureProvider inferenceMode cultureInfo allowEmptyValues parentName json =
let inline inRangeDecimal lo hi (v: decimal) : bool = (v >= decimal lo) && (v <= decimal hi)
let inline inRangeFloat lo hi (v: float) : bool = (v >= float lo) && (v <= float hi)
let inline isIntegerDecimal (v: decimal) : bool = Math.Round v = v
Expand Down Expand Up @@ -65,8 +65,15 @@ let rec internal inferType unitsOfMeasureProvider inferenceMode cultureInfo pare
// More interesting types
| JsonValue.Array ar ->
StructuralInference.inferCollectionType
false
(Seq.map (inferType unitsOfMeasureProvider inferenceMode cultureInfo (NameUtils.singularize parentName)) ar)
allowEmptyValues
(Seq.map
(inferType
unitsOfMeasureProvider
inferenceMode
cultureInfo
allowEmptyValues
(NameUtils.singularize parentName))
ar)
| JsonValue.Record properties ->
let name =
if String.IsNullOrEmpty parentName then
Expand All @@ -76,7 +83,9 @@ let rec internal inferType unitsOfMeasureProvider inferenceMode cultureInfo pare

let props =
[ for propName, value in properties ->
let t = inferType unitsOfMeasureProvider inferenceMode cultureInfo propName value
let t =
inferType unitsOfMeasureProvider inferenceMode cultureInfo allowEmptyValues propName value

{ Name = propName; Type = t } ]

InferedType.Record(name, props, false)
1 change: 1 addition & 0 deletions src/FSharp.Data.Xml.Core/XmlInference.fs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ let getInferedTypeFromValue unitsOfMeasureProvider inferenceMode cultureInfo (el
unitsOfMeasureProvider
inferenceMode
cultureInfo
false
element.Name.LocalName

InferedType.Json(jsonType, optional)
Expand Down
Loading
Loading