#30daysofelm 18일째: 파이썬 백엔드에서 JSON 디코딩

30516 단어 elmpython
제 생애 18일째예요.

카탈로그

  • Table of contents

  • About today's project
  • Code
  • Thanks!
  • Ideas
  • 1. Connecting the front-end and back-end

  • 2. Elm code
  • 2.1 Imports, main and subscriptions
  • 2.2 Model
  • 2.3 Requests and planetDecoder
  • 2.4 Update
  • 2.5 View
  • 2.5.1 Show one planet
  • 2.5.2 Show all planets (or error)
  • 2.5.3 View

  • 3. Things others say about JSON in Elm
  • 3.1 JSON in Elm is different
  • 3.2 JSON decoders in Elm are an important concept
  • 4. Conclusion
  • 오늘 프로젝트 정보


    이 과정에서 저는 Elm에서 Python 백엔드에서 JSON을 디코딩하고 배치했습니다.

    비밀 번호


    데모: https://elm-decode-json-from-python-backend.onrender.com/
    백엔드: https://github.com/kristianpedersen/json-elm-astropy-python/blob/main/app.py
    프런트엔드: https://github.com/kristianpedersen/json-elm-astropy-python/blob/main/templates/src/Main.elm

    감사합니다!


    나의 학습 경험을 쓰고 공유하는 것은 위대한 결정이다.내가 받은 격려와 도움을 봐라.
    예전처럼 Bukkfrig의 평론과 코드는 확실히 사물을 이해하는데 도움이 된다.감사합니다!

    사상


    이제 나는 마침내 이 데이터를 어떻게 처리해야 할지 생각하기 시작할 수 있다.몇 가지 생각:
  • 행성이 빛을 내는 시간을 나타내는 디지털 시계 벽다시 말하면, 당신이 이 행성을 관찰할 때, 당신이 본 시간은 얼마나 니까?이것은 아주 좋은 출발점이다. https://guide.elm-lang.org/effects/time.html
  • 행성 궤도의 간소화 보기로 정렬 방법을 확인합니다.나는 가시화의 목적에 있어서 등거리의 원형 궤도만이 가장 좋은 방법이라고 생각한다.
  • 을 입력하면 날짜를 설정하고 행성이 지정한 날짜에 배열하는 방식을 볼 수 있습니다.
  • 물론 무수한 생각이 있었지만, 나는 가능한 한 간단함을 배웠다.

    1. 프런트엔드 및 백엔드 연결


    Python 서버가 시작되면 다음 두 URL이 제공됩니다.
  • localhost:5000-> 서브index.html
  • localhost:5000/info->JSON API
  • 그 전에 나는 Main.elmmain.js로 컴파일하여 index.html에서 인용할 것이다.
    에서 모든 Python 코드와 배포 프로세스에 대한 자세한 내용을 읽을 수 있습니다.
    코드는 큰 변화가 없지만, 나는 코드가 되돌아오는 데이터 구조를 확실히 개선했다.
    이전 API는 행성 이름을 키로 사용했습니다.나는 지금까지 이런 방법을 좋아하지 않았지만, 내가 그것을 보류한 것은 다음과 같다.
  • 파이톤 함수의 반환 코드에서 목록이나 사전을 어떻게 사용하는지 모르겠습니다.정답return json.dumps(planet_info)
  • 나는 이것이 좋은 연습이라고 생각한다. 왜냐하면 나는 장래에 형식이 좋지 않은 데이터를 처리해야 하기 때문이다.
  • 어제 Bukkfrig의 평론을 읽은 후에 나는 더욱 통용되는 구조로 바뀌었다. 이것은 더욱 좋은 작업 방식이다.
    이전:
    {
        "Mercury": {
            "lightMinutes": 1.2,
            "xyz": [3.4, 5.6, 7.8]
        },
        ...
    }
    
    다음:
    {[
        {
            "name": "Mercury", 
            "lightMinutes": 1.2, 
            "xyz": [3.4, 5.6, 7.8]
        }, 
        ...
    ]}
    

    2.Elm 코드


    2.1 가져오기, 기본 가입 및 가입


    마찬가지로 첫 번째 줄은 자동으로 elm-format로 추가됩니다.
    모든 것을 폭로하는 것은 좋지 않을 수도 있지만, 나는 초보자에게 허락한다.
    module Main exposing (Model(..), Msg(..), Planet, init, main, planetDecoder, planetRequest, subscriptions, update, view, viewPlanet, viewPlanets)
    
    import Browser
    import Html exposing (..)
    import Html.Attributes exposing (..)
    import Html.Events exposing (..)
    import Http
    import Json.Decode exposing (Decoder, field, float, list, map3, string)
    
    우리는 이전에 main 함수를 본 적이 있다.나는 왜 우리가 구독을 지정해야 하는지 알고 싶다. 왜냐하면 내가 아는 바에 의하면 그것들은 어느 곳에서도 사용되지 않기 때문이다.
    main : Program () Model Msg
    main =
        Browser.element
            { init = init
            , update = update
            , subscriptions = subscriptions
            , view = view
            }
    
    
    subscriptions : Model -> Sub Msg
    subscriptions model =
        Sub.none
    

    2.2 모형


    type Model
        = Failure String
        | FirstClick
        | Loading
        | Success (List Planet)
    
    
    init : () -> ( Model, Cmd Msg )
    init _ =
        ( FirstClick, Cmd.none )
    
    대부분의 경우 모델은 몇 개의 문자열이나 숫자의 기록일 뿐이다.
    현재, 그것은 앞부분의 네 가지 다른 상태를 묘사하고 있다.
    AFailure는 잘못된 정보를 가지고 있는데 그 다음 두 개는 관련 데이터가 없다. ASuccess는 행성 목록을 포함한다.init 좀 이상해 보이지만 the official guide에서 복사해 왔어요.
    잠시 후 FirstClick 함수에 단추가 표시되는 것을 볼 수 있습니다.

    2.3 디코더 요청 및 계획


    fetchPlanets : Cmd Msg
    fetchPlanets =
        Http.get
            { url = "info"
            , expect = Http.expectJson PlanetRequest (Json.Decode.list planetDecoder)
            }
    
    
    type alias Planet =
        { name : String
        , lightMinutes : Float
        , xyz : List Float
        }
    
    
    planetDecoder : Decoder Planet
    planetDecoder =
        map3 Planet
            (field "name" string)
            (field "lightMinutes" float)
            (field "xyz" (Json.Decode.list float))
    
    view 부분은 좀 까다롭습니다.솔직히 말해서 나는 단지 그것을 복사하고 붙였을 뿐이지만, 다음은 내가 그것에 대한 이해이다.
  • Http.get URL 및 Expect msg 레코드가 필요합니다.
  • URL은 매우 간단합니다.이런 상황에서 그것은 상대적이기 때문에 로컬과 배치할 때 모두 일을 할 수 있다.
  • Http.get 더 복잡해요.Elm의 관점에서 볼 때 우리는 JSON 식당에서 일한다고 상상해 보자.
  • Expect msg: 새로운 JSON 주문이 있습니다.
  • Http.ExpectJson: 주문서에'PlanetRequest'라는 이름이 표시되어야 합니다.
  • PlanetRequest: 이 주문을 하기 위해서 행성 디코더를 준비해야 합니다.
  • 형식 서명과 같이 Json.Decode.list PlanetDecoderfetchPlanets로 Elm이 실행될 때 어떻게 실행하는지 알 수 있습니다.
    유형 별칭은 Elm planet이 무엇인지, 디코더는 JSON planet이 무엇인지 설명합니다.

    2.4 업데이트


    type Msg
        = GetPlanets
        | PlanetRequest (Result Http.Error (List Planet))
    
    
    update : Msg -> Model -> ( Model, Cmd Msg )
    update msg model =
        case msg of
            GetPlanets ->
                ( Loading, fetchPlanets )
    
            PlanetRequest result ->
                case result of
                    Ok planetData ->
                        ( Success planetData, Cmd.none )
    
                    Err errorMessage ->
                        ( Failure (errorMessage |> Debug.toString), Cmd.none )
    
    업데이트 기능 메시지는 무엇을 받을 수 있는지 알려 줍니다.
  • Cmd Msg: GetPlanets 메시지를 보내고Python API에서 행성에 대한 간단한 정보를 얻습니다.
  • Loading: 이것은 PlanetRequest result 함수에서 되돌아오는 내용입니다.
  • 결과fetchPlanets 또는Ok 이 두 메시지는 모두 관련 변수가 있다. https://package.elm-lang.org/packages/elm/core/latest/ResultErrSuccess 메시지는 현재 모델의 일부분이 되었고 우리는 보기 함수에서 볼 수 있다고 생각합니다.

    2.5 뷰


    이 모든 것은 하나의 보기 함수로 표시할 수 있지만, 나는 Bukkrig의 예를 들어 그것을 분리할 것이다.
    나는 이런 코드를 즐겨 읽는다.내가 무엇을 보고 있는지 더 쉽게 알 수 있을 뿐만 아니라, 그것은 유연한 설정을 제공했다.
    다음 세 가지 기능에 대한 설명입니다.
  • 행성을 어떻게 보여주나요
  • 모형의 모든 행성을 어떻게 표시하는가
  • 보기 기능 자체는 고급 개요로 잘 이해할 수 있습니다.
  • viewPlanets : Model -> Html Msg
    viewPlanets model =
        case model of
            FirstClick ->
                button [ onClick GetPlanets ] [ text "Get planets" ]
    
            Loading ->
                text "beep boop lol"
    
            Success planetData ->
                div []
                    [ button [ onClick GetPlanets, style "display" "block" ] [ text "Refresh" ]
                    , div [] <| List.map viewPlanet planetData
                    ]
    
            Failure errorMessage ->
                div []
                    [ button [ onClick GetPlanets ] [ text "Try Again!" ]
                    , p [] [ text ("Error message: " ++ errorMessage) ]
                    ]
    
    
    view : Model -> Html Msg
    view model =
        div []
            [ h1 [] [ text "It's planet time" ]
            , viewPlanets model
            ]
    

    2.5.1 행성 하나 보여주기


    처음에 나는 이렇게 썼다.
    viewPlanet : Planet -> Html Msg
    viewPlanet { name, lightMinutes } =
        div []
            [ h1 [] [ text name ]
            , p [] [ text ((lightMinutes |> String.fromFloat) ++ " light minutes away") ]
            ]
    
    그러나 우리는 Failure만 쓸 수 있고 { name, lightMinutes, xyz }만 쓸 수 있다.planet에 우리는 viewPlanetplanet.name를 써야 한다.
    viewPlanet : Planet -> Html Msg
    viewPlanet planet =
        div []
            [ h1 [] [ text planet.name ]
            , p [] [ text ((planet.lightMinutes |> String.fromFloat) ++ " light minutes away") ]
            ]
    
    나는 마지막으로 읽는 것이 더 쉽다고 생각한다. 왜냐하면 나는 planet.lightMinutesname가 어디에서 왔는지 알고 있기 때문이다.코드 주체를 스캔할 때, 나는 lightMinutes 파라미터의 결과를 신속하게 볼 수 있다.
    첫 번째 예는 매우 좋다. 왜냐하면 유형 주석은 나로 하여금 이 물건들이 어디에서 왔는지 알게 하지만, 나는 마지막 예가 더 좋다고 생각한다.

    2.5.2 모든 행성 표시(또는 오류)


    이 함수는 행성을 표시할 뿐만 아니라, 나는 그것이 반드시 이름을 바꾸어야 한다고 생각한다.아마도 Planet 또는 viewModel?
    viewPlanets : Model -> Html Msg
    viewPlanets model =
        case model of
            FirstClick ->
                button [ onClick GetPlanets ] [ text "Get planets" ]
    
            Loading ->
                text "beep boop lol"
    
            Success planetData ->
                div []
                    [ button [ onClick GetPlanets, style "display" "block" ] [ text "Refresh" ]
                    , div [] <| List.map viewPlanet planetData
                    ]
    
            Failure errorMessage ->
                div []
                    [ button [ onClick GetPlanets ] [ text "Try Again!" ]
                    , p [] [ text ("Error message: " ++ errorMessage) ]
                    ]
    
    나는 이 책의 읽기 쉬운 성질을 정말 좋아한다.처음 클릭한 경우 버튼이 표시됩니다.불러오는 중이면, 예쁜 작은 메시지 등이 표시됩니다.viewCurrentState 지점에서 우리는 Success planetdata 목록의 각 항목에 viewPlanet를 적용하고 planetData의 본문을 기입했다.아뇨.div 지점에 대해 나는 놀랍게도 official JSON guide 나처럼 오류 메시지가 나타나지 않았다.이것은 매우 도움이 된다.

    2.5.3 보기


    view : Model -> Html Msg
    view model =
        div []
            [ h1 [] [ text "It's planet time" ]
            , viewPlanets model
            ]
    
    좋고 간단해.여기서 우리는 다른 내용을 기입하여 위로 이동하거나 아래로 이동Failure하거나 중복 사용할 수 있다.

    3. 다른 사람들이 Elm의 JSON에 대한 견해


    Elm에는 JSON에 대한 토론이 많은데, 나는 왜 그런지 안다.
    내 코드만 봐도 데이터에 대한 정확한 설명을 보니 기쁘다.viewPlanetsundefined는 점점 먼 기억처럼 느껴진다.

    3.1 Elm의 JSON은 다릅니다.


    이상하게도 내가 자바스크립트에서 별로 생각하지 않았던 것들은 Elm에서 골치 아프게 한다.내 경험에 따르면 지금까지 다른 Elm 개념은 좀 더 쉬웠다.
    그러나 일정한 끈기와 도움을 구하려는 의지로 결국 성공할 것이다.

    3.2 Elm의 JSON 디코더는 중요한 개념이다


    나는 사람들이 말하는 두 번째 일을 들었다.

    I have heard a bunch of stories of folks finding bugs in their server code as they switched from JS to Elm. The decoders people write end up working as a validation phase, catching weird stuff in JSON values. So when NoRedInk switched from React to Elm, it revealed a couple bugs in their Ruby code!


    https://guide.elm-lang.org/effects/json.html

    Writing decoders that can fail, might seem a bit scary. But failing decoders have helped me discover bugs in the backend code, which I never noticed in the JavaScript apps using those endpoints, specifically because the decoders I wrote failed whenever the data from the server didn't line up with my expectations


    https://functional.christmas/2019/8

    I think for me, understanding JSON decoding is what got me to finally understand Elm and Haskell.


    It's one of those things that gives your app a rock solid foundation and prevents stupid runtime exceptions. It's part of what could make you considerably happier than the average JS/TS developer in the long run 😄


    4. 결론


    지금까지 Elm을 배우는 데 가장 도전적인 부분이었지만 성공했습니다.생성된 코드로는 괜찮지만 JavaScript와는 많이 다릅니다.
    내가 이 과정에서 얻은 도움은 놀랍다. 일부 원인은 내가'JSON 디코더가 어떻게 작동하는가?'만 묻는 것이 아니라 나의 사고 과정과 코드를 공유했기 때문이라고 생각한다.
    나도 포기하지 않아서 기쁘다.이것은 다음과 같은 사실 덕분이다. 어떤 Elm 코드나 지식도 나의 일상적인 도전에서 매우 중요하다.
    만약 내가 단지 10분의 일을 하고 나서 적어 놓는다면, 이것은 매우 중요하다.내가 엉망이거나 바쁜 나날을 보냈을 때, 이런 관용은 매우 좋았고, 효과적이고 지속 가능한 것으로 증명되었다.
    내일은 내가 좀 더 편한 일을 할 것 같지만, 누가 알겠는가?읽어주셔서 감사합니다. 내일 봐요!

    좋은 웹페이지 즐겨찾기