Search code examples
encodeelmencoder

Elm : How to Encode Nested objects


Model

type alias Model {
      name : String
    , poi_coordinates : Coordinates
}

type alias Coordinates = 
    {
        coord_type : String
    ,   coordinates : List Float
    }


poiFormEncoder : Model -> Encode.Value
poiFormEncoder model =
    Encode.object
        [ 
          ( "name", Encode.string model.name )
        , ( "type", Encode.string model.poi_coordinates.coord_type)
        , ( "poi_coordinates", Encode.array Encode.float (Array.fromList model.poi_coordinates.coordinates) )
        ]

Can i ask how to encode for this data type? I have no idea , and the encoder i did gives no coordinates fill. Any help is really appreciate. The Json file format is at below

[
   {
        "name": "Mcd",
        "coordinates": {
            "type": "Point",
            "coordinates": [
                101.856603,
                2.924
            ]
        } 
    },
         .
         .
         .
]

Solution

  • You can nest calls to Json.Encode.object. Each time you want a new object in the output, you need another one, e.g:

    poiFormEncoder : Model -> Encode.Value
    poiFormEncoder model =
        Encode.object
            [ ( "name", Encode.string model.name )
            , ( "coordinates"
              , Encode.object
                    [ ( "type", Encode.string model.poi_coordinates.coord_type )
                    , ( "coordinates", Encode.list Encode.float model.poi_coordinates.coordinates )
                    ]
              )
            ]
    

    This should make sense: it is a list of (key, value) pairs, and the value should be another object.

    On a side note, it will depend on your use case, but your Coordinates type looks like a prime candidate for a custom Elm type, e.g:

    type Coordinates 
        = Point { x : Float, y : Float }
        | Polar { r : Float, t : Float }
        | ...
    

    If you find you are doing a lot of checking the string type value and then dealing with the coordinates accordingly, something like this might be a much nicer structure to use internally. Of course, the best representation will depend on how you are using the type.