How to write a generic JSON decoder?

What you can do is lift all the fields to strings.

module Main exposing (main)
 
import Html exposing (text)
import Json.Decode as Json 
import Dict

fromBool val = 
    if val then "True" else "False"

asString = 
    Json.oneOf 
        [ Json.string 
        , Json.map String.fromInt Json.int
        , Json.map String.fromFloat Json.float
        , Json.map fromBool Json.bool
        , Json.null ""
        ]

myDecoder = 
    Json.map3 (\name age powers -> {name=name, age = age, powers = powers} )
        (Json.field "name" Json.string)
        (Json.field "age" Json.int)
        powersDecoder
        
 
powersDecoder = 
    Json.map (Dict.filter (\k _ -> not (List.member k ["name", "age" ]))) (Json.dict asString)  
 
 
inputJson = """
{
   "name": "rupert",
   "age": 42,
   "x-superpower": "teleportation",
   "x-king": true,
   "x-op": 9001
}
"""



main =
     text <| Debug.toString <| Json.decodeString myDecoder inputJson 

link to Ellie

Of course, this would not work for collection fields (arrays, objects) but you can extend asString to cover those cases if you need to.

1 Like