From 0e7d609881395a6ca508fb0da9a4e05afe48c218 Mon Sep 17 00:00:00 2001 From: Smaug123 <3138005+Smaug123@users.noreply.github.com> Date: Fri, 10 Jul 2026 10:57:03 +0100 Subject: [PATCH 1/2] Handle nullable values in JsonParse --- ConsumePlugin/GeneratedJson.fs | 6 ++ ConsumePlugin/JsonRecord.fs | 1 + .../TestJsonParse/TestJsonParse.fs | 55 +++++++++++++++++++ WoofWare.Myriad.Plugins/JsonParseGenerator.fs | 9 ++- 4 files changed, 70 insertions(+), 1 deletion(-) diff --git a/ConsumePlugin/GeneratedJson.fs b/ConsumePlugin/GeneratedJson.fs index 92f3e1ee..7ba247f4 100644 --- a/ConsumePlugin/GeneratedJson.fs +++ b/ConsumePlugin/GeneratedJson.fs @@ -94,6 +94,11 @@ namespace ConsumePlugin module JsonRecordType = /// Parse from a JSON node. let jsonParse (node : System.Text.Json.Nodes.JsonNode) : JsonRecordType = + let arg_6 = + match node.["g"] |> Option.ofObj with + | None -> System.Nullable () + | Some v -> v.AsValue().GetValue () |> System.Nullable + let arg_5 = match node.["f"] |> Option.ofObj with | None -> @@ -194,6 +199,7 @@ module JsonRecordType = D = arg_3 E = arg_4 F = arg_5 + G = arg_6 } namespace ConsumePlugin diff --git a/ConsumePlugin/JsonRecord.fs b/ConsumePlugin/JsonRecord.fs index a44aa902..7a7da6d3 100644 --- a/ConsumePlugin/JsonRecord.fs +++ b/ConsumePlugin/JsonRecord.fs @@ -27,6 +27,7 @@ type JsonRecordType = D : InnerType E : string array F : int[] + G : System.Nullable } [] diff --git a/WoofWare.Myriad.Plugins.Test/TestJsonParse/TestJsonParse.fs b/WoofWare.Myriad.Plugins.Test/TestJsonParse/TestJsonParse.fs index d60fcb70..6c702834 100644 --- a/WoofWare.Myriad.Plugins.Test/TestJsonParse/TestJsonParse.fs +++ b/WoofWare.Myriad.Plugins.Test/TestJsonParse/TestJsonParse.fs @@ -30,6 +30,61 @@ module TestJsonParse = } E = [| "something" ; "else" |] F = [||] + G = System.Nullable () + } + + let actual = s |> JsonNode.Parse |> JsonRecordType.jsonParse + actual |> shouldEqual expected + + [] + let ``Single example with explicit null`` () = + let s = + """ +{ + "a": 3, "another-thing": "hello", "hi": [6, 1], "d": {"something": "oh hi"}, "g": null, + "e": ["something", "else"], "f": [] +} +""" + + let expected = + { + A = 3 + B = "hello" + C = [ 6 ; 1 ] + D = + { + Thing = "oh hi" + } + E = [| "something" ; "else" |] + F = [||] + G = System.Nullable () + } + + let actual = s |> JsonNode.Parse |> JsonRecordType.jsonParse + actual |> shouldEqual expected + + [] + let ``Single example, nullable provided`` () = + let s = + """ +{ + "a": 3, "another-thing": "hello", "hi": [6, 1], "d": {"something": "oh hi"}, "g": 3, + "e": ["something", "else"], "f": [] +} +""" + + let expected = + { + A = 3 + B = "hello" + C = [ 6 ; 1 ] + D = + { + Thing = "oh hi" + } + E = [| "something" ; "else" |] + F = [||] + G = System.Nullable 3 } let actual = s |> JsonNode.Parse |> JsonRecordType.jsonParse diff --git a/WoofWare.Myriad.Plugins/JsonParseGenerator.fs b/WoofWare.Myriad.Plugins/JsonParseGenerator.fs index 6871e68f..511b0569 100644 --- a/WoofWare.Myriad.Plugins/JsonParseGenerator.fs +++ b/WoofWare.Myriad.Plugins/JsonParseGenerator.fs @@ -125,7 +125,14 @@ module internal JsonParseGenerator = = let keyArg = SynExpr.createLongIdent [ "kvp" ; "Key" ] |> SynExpr.paren - let valueArg = SynExpr.createLongIdent [ "kvp" ; "Value" ] + let valueArg = + let value = SynExpr.createLongIdent [ "kvp" ; "Value" ] + + if valueTypeIsNullable then + value + |> SynExpr.pipeThroughFunction (SynExpr.createLongIdent [ "Option" ; "ofObj" ]) + else + value let value = if valueTypeIsNullable then From 4cb80f7554d5dde409313648103ed34cd1fb46b8 Mon Sep 17 00:00:00 2001 From: Smaug123 <3138005+Smaug123@users.noreply.github.com> Date: Fri, 10 Jul 2026 11:04:50 +0100 Subject: [PATCH 2/2] Repair test --- ConsumePlugin/GeneratedJson.fs | 22 +++++++++++++++++-- ConsumePlugin/JsonRecord.fs | 3 ++- .../TestJsonParse/TestJsonParse.fs | 14 +++++++----- 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/ConsumePlugin/GeneratedJson.fs b/ConsumePlugin/GeneratedJson.fs index 7ba247f4..b7766a9e 100644 --- a/ConsumePlugin/GeneratedJson.fs +++ b/ConsumePlugin/GeneratedJson.fs @@ -7,6 +7,7 @@ namespace ConsumePlugin +open System.Collections.Generic open System.Text.Json.Serialization /// Module containing JSON serializing methods for the InternalTypeNotExtensionSerial type @@ -36,6 +37,7 @@ module internal InternalTypeNotExtensionSerial = node :> _ namespace ConsumePlugin +open System.Collections.Generic open System.Text.Json.Serialization /// Module containing JSON serializing extension members for the InternalTypeExtension type @@ -96,8 +98,24 @@ module JsonRecordType = let jsonParse (node : System.Text.Json.Nodes.JsonNode) : JsonRecordType = let arg_6 = match node.["g"] |> Option.ofObj with - | None -> System.Nullable () - | Some v -> v.AsValue().GetValue () |> System.Nullable + | None -> + raise ( + System.Collections.Generic.KeyNotFoundException ( + sprintf "Required key '%s' not found on JSON object" ("g") + ) + ) + | Some node -> + node.AsObject () + |> Seq.map (fun kvp -> + let key = (kvp.Key) + let value = kvp.Value |> Option.ofObj + + key, + match value with + | None -> System.Nullable () + | Some v -> v.AsValue().GetValue () |> System.Nullable + ) + |> dict let arg_5 = match node.["f"] |> Option.ofObj with diff --git a/ConsumePlugin/JsonRecord.fs b/ConsumePlugin/JsonRecord.fs index 7a7da6d3..5111cf95 100644 --- a/ConsumePlugin/JsonRecord.fs +++ b/ConsumePlugin/JsonRecord.fs @@ -1,5 +1,6 @@ namespace ConsumePlugin +open System.Collections.Generic open System.Text.Json.Serialization module Literals = @@ -27,7 +28,7 @@ type JsonRecordType = D : InnerType E : string array F : int[] - G : System.Nullable + G : IDictionary> } [] diff --git a/WoofWare.Myriad.Plugins.Test/TestJsonParse/TestJsonParse.fs b/WoofWare.Myriad.Plugins.Test/TestJsonParse/TestJsonParse.fs index 6c702834..fc3c1788 100644 --- a/WoofWare.Myriad.Plugins.Test/TestJsonParse/TestJsonParse.fs +++ b/WoofWare.Myriad.Plugins.Test/TestJsonParse/TestJsonParse.fs @@ -1,5 +1,7 @@ namespace WoofWare.Myriad.Plugins.Test +open System +open System.Collections.Generic open System.Text.Json.Nodes open ConsumePlugin open NUnit.Framework @@ -14,7 +16,7 @@ module TestJsonParse = let s = """ { - "a": 3, "another-thing": "hello", "hi": [6, 1], "d": {"something": "oh hi"}, + "a": 3, "another-thing": "hello", "hi": [6, 1], "d": {"something": "oh hi"}, "g": {}, "e": ["something", "else"], "f": [] } """ @@ -30,7 +32,7 @@ module TestJsonParse = } E = [| "something" ; "else" |] F = [||] - G = System.Nullable () + G = dict [] } let actual = s |> JsonNode.Parse |> JsonRecordType.jsonParse @@ -41,7 +43,7 @@ module TestJsonParse = let s = """ { - "a": 3, "another-thing": "hello", "hi": [6, 1], "d": {"something": "oh hi"}, "g": null, + "a": 3, "another-thing": "hello", "hi": [6, 1], "d": {"something": "oh hi"}, "g": {"hi": null}, "e": ["something", "else"], "f": [] } """ @@ -57,7 +59,7 @@ module TestJsonParse = } E = [| "something" ; "else" |] F = [||] - G = System.Nullable () + G = dict [ "hi", Nullable () ] } let actual = s |> JsonNode.Parse |> JsonRecordType.jsonParse @@ -68,7 +70,7 @@ module TestJsonParse = let s = """ { - "a": 3, "another-thing": "hello", "hi": [6, 1], "d": {"something": "oh hi"}, "g": 3, + "a": 3, "another-thing": "hello", "hi": [6, 1], "d": {"something": "oh hi"}, "g": {"hi": 3}, "e": ["something", "else"], "f": [] } """ @@ -84,7 +86,7 @@ module TestJsonParse = } E = [| "something" ; "else" |] F = [||] - G = System.Nullable 3 + G = dict [ "hi", Nullable 3 ] } let actual = s |> JsonNode.Parse |> JsonRecordType.jsonParse