Skip to content
This repository has been archived by the owner on Nov 8, 2019. It is now read-only.

added Converter #145

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
8 changes: 8 additions & 0 deletions paket.dependencies
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,11 @@ group Demos
nuget Fable.FontAwesome
nuget Fable.FontAwesome.Free
nuget Fable.Import.HMR

group WebApi
framework >= net46
source https://www.nuget.org/api/v2
nuget Microsoft.AspNet.WebApi 5.2.3.0
nuget Microsoft.AspNet.WebApi.Core 5.2.3.0
nuget Microsoft.AspNet.WebApi.Client 5.2.3.0
nuget Newtonsoft.Json >= 11.0.2
3,270 changes: 1,642 additions & 1,628 deletions paket.lock

Large diffs are not rendered by default.

25 changes: 25 additions & 0 deletions src/Thoth.Json.Net/Converters.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
module Thoth.Json.Net.Converters

open Newtonsoft.Json
open Newtonsoft.Json.Linq

type Converter (?isCamelCase : bool, ?extra: ExtraCoders) =
inherit JsonConverter()

override __.CanConvert(t) = true

override __.WriteJson(writer, value, _) =
let t = value.GetType()
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will fails if value is None. See for the solution

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm.
If I write override __.WriteJson(writer, (value : 'T), _) =, value must be an object and can't be a value type anymore.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MangelMaxime , please ignore last comment. the value must be an obj, otherwise it cannnot be represented as Json. And for the very same reason the value cannot be simply None. Simplest value should be ``[| None |].

However, it still doesn't work . If code is changed to

  override __.WriteJson(writer, (value:'t), _) = 
        let encoder = Encode.Auto.generateEncoderCached<'t>(?isCamelCase=isCamelCase, ?extra=extra)
        (encoder value).WriteTo(writer)
        writer.Flush()

WriteTo fails in tests with System.ArgumentException: "Could not determine JSON object type for type Record9."

let encoder = Encode.Auto.generateEncoderCached(t, ?isCamelCase=isCamelCase, ?extra=extra)
(encoder value).WriteTo(writer)
writer.Flush()

override __.ReadJson(reader, t, _, _) =
let decoder = Decode.Auto.generateDecoderCachedByType(t, ?isCamelCase=isCamelCase, ?extra=extra)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would use the version which use the generic type here too (same as above)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, it is not like above. t is of System.Type (and not generic as the value)

let json = JObject.Load(reader).ToString()
Decode.fromString decoder json
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should use Decode.unsafeFromString instead of manually handling the Result type

|> function
| Ok value -> value
| Error er -> failwith er


3 changes: 3 additions & 0 deletions src/Thoth.Json.Net/Decode.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1033,6 +1033,9 @@ module Decode =
/// ATTENTION: Use this only when other arguments (isCamelCase, extra) don't change
static member generateDecoderCached<'T> (?isCamelCase : bool, ?extra: ExtraCoders): Decoder<'T> =
let t = typeof<'T>
Auto.generateDecoderCachedByType (t, ?isCamelCase=isCamelCase, ?extra=extra )

static member generateDecoderCachedByType (t:System.Type, ?isCamelCase : bool, ?extra: ExtraCoders): Decoder<'T> =
let decoderCrate =
Util.CachedDecoders.Value.GetOrAdd(t, fun t ->
let isCamelCase = defaultArg isCamelCase false
Expand Down
27 changes: 14 additions & 13 deletions src/Thoth.Json.Net/Thoth.Json.Net.fsproj
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<PropertyGroup>
<Description>Elm-inspired encoder and decoder for JSON targetting .Net and NetCore runtime</Description>
<PackageProjectUrl>https://github.com/MangelMaxime/Thoth</PackageProjectUrl>
<PackageLicenseUrl>https://github.com/MangelMaxime/Thoth/blob/master/LICENSE.md</PackageLicenseUrl>
<RepositoryUrl>https://github.com/MangelMaxime/Thoth</RepositoryUrl>
<PackageTags>fsharp;json</PackageTags>
<Authors>Maxime Mangel</Authors>
<Version>3.0.0-beta-002</Version>
</PropertyGroup>
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net46</TargetFrameworks>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
<ItemGroup>
<Compile Include="Types.fs" />
<Compile Include="Decode.fs" />
<Compile Include="Encode.fs" />
<Compile Include="Extra.fs" />
</ItemGroup>
<Import Project="..\..\.paket\Paket.Restore.targets" />
</PropertyGroup>
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net46</TargetFrameworks>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
<ItemGroup>
<Compile Include="Types.fs" />
<Compile Include="Decode.fs" />
<Compile Include="Encode.fs" />
<Compile Include="Extra.fs" />
<Compile Include="Converters.fs" />
</ItemGroup>
<Import Project="..\..\.paket\Paket.Restore.targets" />
</Project>
11 changes: 11 additions & 0 deletions src/Thoth.Json.WebApi/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Usage

```fsharp

open Thoth.Json.WebApi

[<WithThothJsonNet>]
type FableController () =
inherit ApiController ()

```
18 changes: 18 additions & 0 deletions src/Thoth.Json.WebApi/Thoth.Json.WebApi.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
namespace Thoth.Json.WebApi
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this belongs to Thoth.Json.Net

You are adding Microsoft.AspNet.WebApi as a dependencies of Thoth.Json.Net which is not needed. It should be in the future a separate package like Thoth.Json.Giraffe

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the new package Thoth.Json.WepApi.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it. Thoth.Json,Giraffe is now also in its own repository :-)


open System.Web.Http.Controllers
open System.Net.Http.Formatting
open Newtonsoft.Json
open Thoth.Json.Net

type WithThothJsonNetAttribute(?isCamelCase : bool, ?extra : ExtraCoders) =
inherit System.Attribute()
interface IControllerConfiguration with
member __.Initialize((controllerSettings : HttpControllerSettings), _) =
let converter =
Thoth.Json.Net.Converters.Converter(?isCamelCase = isCamelCase, ?extra = extra)
let thothFormatter =
JsonMediaTypeFormatter
(SerializerSettings = JsonSerializerSettings(Converters = [| converter |]))
controllerSettings.Formatters.Clear()
controllerSettings.Formatters.Add thothFormatter
15 changes: 15 additions & 0 deletions src/Thoth.Json.WebApi/Thoth.Json.WebApi.fsproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFramework>net46</TargetFramework>
<DebugType>portable</DebugType>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="../Thoth.Json.Net/Thoth.Json.Net.fsproj" />
</ItemGroup>
<ItemGroup>
<Compile Include="Thoth.Json.WebApi.fs" />
</ItemGroup>
<Import Project="..\..\.paket\Paket.Restore.targets" />
</Project>
7 changes: 7 additions & 0 deletions src/Thoth.Json.WebApi/paket.references
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
FSharp.Core

group WebApi
Microsoft.AspNet.WebApi
Microsoft.AspNet.WebApi.Core
Microsoft.AspNet.WebApi.Client
Newtonsoft.Json
1 change: 1 addition & 0 deletions tests/Main.fs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ open Util.Testing
let main args =
testList "All" [ Tests.Decode.tests
Tests.Encode.tests
Tests.Converter.tests
]
|> runTestsWithArgs defaultConfig args

Expand Down
61 changes: 61 additions & 0 deletions tests/Tests.Json.Converter.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
module Tests.Converter

open Newtonsoft.Json
open Expecto
open Util.Testing

let encodeWithConverter<'T> (converter: JsonConverter) (space: int) (value: obj) : string =
let format = if space = 0 then Formatting.None else Formatting.Indented
let settings = JsonSerializerSettings(Converters = [|converter|],
Formatting = format,
DateTimeZoneHandling = DateTimeZoneHandling.Utc )
JsonConvert.SerializeObject(value, settings)

let decodeStringWithConverter<'T> (converter: JsonConverter) (json: string): Result<'T, string> =
try
JsonConvert.DeserializeObject<'T>(json, converter) |> Ok
with ex ->
Error("Given an invalid JSON: " + ex.Message)


type MyUnion = Foo of int

type Record2 =
{ a : float
b : float }

type Record9 =
{ a: int
b: string
c: (bool * int) list
d: MyUnion
e: Map<string, Record2>
f: System.DateTime
}

let tests : Test =
testList "Thoth.Json.Converter" [

testList "Basic" [
testCase "roundtrip works" <| fun _ ->
let converter = Thoth.Json.Net.Converters.Converter false
let json =
{ a = 5
b = "bar"
c = [false, 3; true, 5; false, 10]
d = Foo 14
e = Map [("oh", { a = 2.; b = 2. }); ("ah", { a = -1.5; b = 0. })]
f = System.DateTime.Now
} |> encodeWithConverter converter 4
let result = decodeStringWithConverter converter json
match result with
| Error er -> failwith er
| Ok r2 ->
equal 5 r2.a
equal "bar" r2.b
equal [false, 3; true, 5; false, 10] r2.c
equal (Foo 14) r2.d
equal -1.5 (Map.find "ah" r2.e).a
equal 2. (Map.find "oh" r2.e).b
]
]
1 change: 1 addition & 0 deletions tests/dotnet/Thoth.Tests.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<Compile Include="../Util.fs" />
<Compile Include="../Tests.Json.Decode.fs" />
<Compile Include="../Tests.Json.Encode.fs" />
<Compile Include="../Tests.Json.Converter.fs" />
<Compile Include="../Main.fs" />
</ItemGroup>
<Import Project="..\..\.paket\Paket.Restore.targets" />
Expand Down
1 change: 1 addition & 0 deletions tests/dotnet/paket.references
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
FSharp.Core
Expecto
Newtonsoft.Json