thoth-org/Thoth.Json

Add Decode.listLength, Decode.arrayLength

Closed this issue · 5 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.

Hello @Swoorup,

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

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
njlr commented

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 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

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.