Thoth.Json icon indicating copy to clipboard operation
Thoth.Json copied to clipboard

Add Decode.listLength, Decode.arrayLength

Open Swoorup opened this issue 3 years ago • 4 comments

When you are storing varying elements in an array, it would be nicer if we can also discriminate using their length, So subsequently you could use Decode.andThen followed by sets of valid Decode.index patterns.

Swoorup avatar Feb 11 '22 07:02 Swoorup

Hello @Swoorup,

To be sure, I understand could you please provide an example (JSON + F# code) of what you are trying to do?

MangelMaxime avatar Feb 11 '22 10:02 MangelMaxime

Don't have an F# code at the moment but for example.

You could store notes as an array instead of object for compression.

[
    [1, "first note", "2016-08-14 15:34:32Z", ... more properties],
    [2, "second note", "2016-08-14 16:03:12Z", ... more properties],
    [1, "delete"]
  ]

Here the third is actually a command to delete the first note identified by its length of 2.

Which roughly translate to

type Note = 
   | Note of id: int * string * DateTime
   | DeleteCommand of id: int

Swoorup avatar Feb 11 '22 11:02 Swoorup

This should work, although there may be potential for efficiency gains by not decoding the whole list:

module Decode =

  let listLength : Decoder<int> =
    Decode.list Decode.value
    |> Decode.map List.length

But perhaps this is better?

module Decode =

  let note : Decoder<Note> =
    Decode.oneOf
      [
        Decode.tuple3 Decode.int Decode.string Decode.datetime
        |> Decode.map Note

        Decode.index 0 Decode.int
        |> Decode.map DeleteCommand
      ]

Note that order of the oneOf elements is significant here, since a valid Note can also decode as a valid DeleteCommand

njlr avatar Mar 20 '22 09:03 njlr

@njlr I am using this for now, I got it from somewhere in the source code which was doing something similar.

  let arrayLength: Decoder<int> =
    fun path value ->
      if Decode.Helpers.isArray value then
        let vArray = Decode.Helpers.asArray value
        Ok vArray.Length
      else
        (path, BadPrimitive("an array", value)) |> Error

Swoorup avatar Mar 20 '22 10:03 Swoorup

I am closing this issue because I think this is a specific use case.

If more people show interest in it, I will reconsider including it in the core library.

Another solution is to create a packages or gist to extends Thoth.Json and make it available to others.

MangelMaxime avatar Nov 09 '22 19:11 MangelMaxime