在Elm中将整数数组解码为Date:Decoder链式调用实现求助
Got it, let's break this down step by step! You already know how to decode your JSON into a list of integers—great start. The missing piece is using Elm's Decode.andThen to chain decoders together, which lets you take the output of one decoder and use it to drive the next step (turning that integer list into a Date and mapping it to your custom model).
Step 1: Build a Decoder to Convert Integer Lists → Dates
First, let's assume your JSON has an array like [2024, 5, 20] representing year, month, day. We'll write a helper decoder that validates the list structure and converts it to a Date:
import Date exposing (Date) import Json.Decode as Decode exposing (Decoder, int, list, andThen, fail) -- Decodes a list of 3 integers into a valid Date listToDateDecoder : Decoder Date listToDateDecoder = list int |> andThen (\intList -> case intList of -- Check for exactly 3 integers (year, month, day) [ year, month, day ] -> -- Try to create a Date from the values case Date.fromCalendarDate year (Date.Month.fromNumber month) day of Ok validDate -> Decode.succeed validDate Err errorMsg -> Decode.fail ("Invalid date values: " ++ errorMsg) -- Handle lists that don't match the expected length _ -> Decode.fail "Expected a list of exactly 3 integers (year, month, day)" )
How this works:
- We first run
list intto pull the integer list from JSON. andThenpasses that list to our custom logic:- If the list has 3 elements, we attempt to create a
Dateusing Elm's built-in date validation. - If the date is valid, we return
Decode.succeed validDateto pass the date forward. - If the list is the wrong length or the date is invalid (like February 30th), we return
Decode.failwith a clear error message.
- If the list has 3 elements, we attempt to create a
Step 2: Map the Date Decoder to Your Custom Model
Let's say your custom model looks like this—with a date field plus other data points:
type alias Event = { title : String , eventDate : Date , attendeeCount : Int }
We'll build a full model decoder by combining our listToDateDecoder with decoders for other fields using Decode.mapN (use map2, map3, etc., based on how many fields your model has):
eventDecoder : Decoder Event eventDecoder = Decode.map3 Event (Decode.field "title" Decode.string) (Decode.field "dateArray" listToDateDecoder) -- Plug in our custom date decoder here (Decode.field "attendeeCount" Decode.int)
Test with Example JSON
Here's a sample JSON object you can use to test:
{ "title": "Summer Workshop", "dateArray": [2024, 7, 10], "attendeeCount": 28 }
Run the decoder with:
Decode.decodeString eventDecoder yourJsonString
This will return either Ok { title = "Summer Workshop", eventDate = <Date>, attendeeCount = 28 } or an Err with a message explaining what went wrong (e.g., invalid date, incorrect list length).
Quick Notes
- Error Handling: Elm decoders are strict by design, so accounting for all failure cases (like wrong list length) makes your code more robust and easier to debug.
- Using Time.Posix?: If you're working with
Time.Posixinstead ofDate.Date, the pattern is identical—just replace theDate.fromCalendarDatelogic with code to convert your integer list to a Posix timestamp (e.g., usingTime.millisToPosixif your list is a millisecond timestamp).
内容的提问来源于stack exchange,提问作者user2605836

