#30daysofelm 16일차: JSON으로 약간 덜 고군분투

12614 단어 elm
이것은 나의 16일째이다.

볼프강 슈스터 덕분에
, 을 위한 !

또한 오늘 도와주신 Elm Slack Sephi에게도 감사드립니다!

목차


  • Table of contents
  • 1. Simplifying Main.elm
  • 2. Hardcoded JSON with one field
  • 3. Decoding a person object with fields of different types (name, age)
  • 4. Summary

  • 1. Main.elm 단순화



    어제 JSON을 어떻게 처리해야 할지 몰라서 조금 뒤로 물러나면 좋겠다는 생각이 들었다.

    어제, 나는 단순히 9일차부터의 프로젝트를 복사했습니다.

    이것은 내가 더 작업하고 싶은 프로젝트이지만 Main.elm 거의 100줄에 달하는 코드로 구독, cmd msgs 및 외부 API와 통신하는 데 필요한 기타 항목이 포함되어 있습니다.

    미친 것은 아니지만 새로운 개념을 배울 때 방해가 되기에 충분합니다.

    오늘 저에게 더 나은 도움이 될 것으로 생각되는 아주 최소한의 출발점은 다음과 같습니다.

    module Main exposing (main)
    
    import Html exposing (div, text)
    
    
    main =
        div [] [ text "hi" ]
    


    첫 번째 줄은 elm-format 에 의해 자동으로 추가됩니다. Browser.sandbox가 있는 표준 모델 업데이트 보기 아키텍처는 훌륭하지만 JSON 디코딩의 기본을 배울 때 필요하지 않습니다.

    2. 하나의 필드로 하드코딩된 JSON



    다음은 하나의 필드로 JSON 객체를 디코딩하는 매우 기본적인(그리고 어리석은) 예입니다.

    module Main exposing (main)
    
    import Dict exposing (Dict)
    import Html exposing (div, text)
    import Json.Decode exposing (..)
    
    
    name =
        """ {"name": "Kristian"} """
    
    
    getName =
        field "name" string
    
    
    main =
        div []
            [ text
                (case decodeString getName name of
                    Ok result ->
                        result
    
                    Err e ->
                        e |> Debug.toString
                )
            ]
    


    삼중 따옴표는 깔끔합니다. 일반적으로 여러 줄 문자열에 사용되지만 여기에서 사용하면 모든 " 문자 앞에 백슬래시를 넣을 필요가 없습니다.

    JSON 객체 디코딩에는 두 부분이 있습니다. 먼저 Elm이 무엇을 가져와야 하는지 설명하면 다른 함수가 이를 수행합니다.

    여기서 코드의 주요 비트는 decodeString getName name 입니다.

    전체 이름은 JSON.Decode.decodeString 이고 무엇이든 문자열로 변환할 때 원하는 것입니다. :)

    외부 API가 없는 이 접근 방식은 JSON 디코딩에 대한 더 좋은 소개가 될 것이라고 생각합니다. 여러 사람들이 처음에는 이해하는 데 약간 어려움을 겪었기 때문입니다.

    3. 다양한 유형(이름, 나이)의 필드로 사람 객체 디코딩




    person : String
    person =
    """ 
        {
            "person": {
                "name": "Kristian",
                "age": 31
            }
        }
    """
    


    이것은 더 복잡하지만 작업하기도 매우 쉽습니다.

    먼저 어떤 작업을 수행하기 전에 Elm에 필드를 설명합니다.

    howToGetName : Decoder String
    howToGetName =
        field "person" (field "name" string)
    
    
    howToGetAge : Decoder Int
    howToGetAge =
        field "person" (field "age" int)
    
    
    howToGetPerson : Decoder Person
    howToGetPerson =
        map2 Person
            (field "name" string)
            (field "age" int)
    
    
    type alias Person =
        { name : String
        , age : Int
        }
    


    이 글을 쓸 때 JSON guide 에서 map2 줄을 붙여넣었습니다. "사람"필드를 참조하지 않으므로 작동하지 않습니다.

    Failure "Expecting an OBJECT with a field named 'name'" <internals>


    map2List.map 와 동일하지 않지만 방법입니다! 실제 이름은 Json.Decode.map2 입니다.

    유형 서명을 비교해 보겠습니다.

    map : (a -> b) -> List a -> List b

    map2 : (a -> b -> value) -> Decoder a -> Decoder b -> Decoder value


    map2는 두 개의 값ab를 취하여 값을 반환합니다. 그런 다음 두 개의 디코더를 반환하고 하나로 바꿉니다. 아니면 제가 틀렸을 수도 있습니다.

    어쨌든 처리 방법은 다음과 같습니다. 나는 (내 생각에) 모든 것을 문자열, 심지어 문자열로 변환하는 Debug.toString 꽤 일반적인 솔루션을 찾았습니다.

    getInfo : String -> Decoder a -> String
    getInfo sourceJSON decoder =
        case decodeString decoder sourceJSON of
            Ok result ->
                result |> Debug.toString
    
            Err e ->
                e |> Debug.toString
    
    
    main : Html msg
    main =
        div []
            [ text (getInfo person howToGetName)
            , text (getInfo person howToGetAge)
            , text (getInfo person howToGetPerson)
            ]
    
    


    마지막 줄을 작동시키면 한 가지 개선하고 싶은 것이 있습니다. getInfo 전체 결과를 문자열로 변환하지만 개별 필드를 처리하고 싶을 수 있습니다.

    getPersonInfo : String -> Decoder Person -> String
    getPersonInfo sourceJSON decoder =
        case decodeString decoder sourceJSON of
            Ok { name, age } ->
                name ++ ", " ++ (age |> String.fromInt)
    
            Err e ->
                e |> Debug.toString
    
    
    main : Html msg
    main =
        div []
            [ text (getInfo person howToGetName)
            , text (getInfo person howToGetAge)
            , text (getPersonInfo person howToGetPerson)
            ]
    

    Ok result 라고 말하는 대신 resultOk { name, age } 로 분해합니다. 컴파일이 되니까 뭔가 하고 있는 것 같아요.

    4. 요약



    오늘은 그게 다야. 디코딩할 수 있는 방향으로 몇 가지 좋은 조치를 취한 것 같습니다. 그리고 그것으로 재미있는 일을 할 수 있습니다.

    외부 API와 추적해야 하는 모든 추가 코드를 처리하는 대신 가능한 가장 간단한 코드부터 시작하기로 결정한 것이 매우 기쁩니다.

    내일 봐요!

    좋은 웹페이지 즐겨찾기