바둑 배우기 시도 - 유령이 휴고에게 3

50351 단어 hugoghostgo

소개



우리는 back once again에서 ghost2hugo 프로토타입에 대한 작업을 계속할 것입니다. 지금까지 JSON 파일을 열고 데이터를 메모리에 로드하고 첫 번째 게시물에 대한 Markdown을 인쇄할 수 있습니다. 다음 단계는 백업에 포함된 모든 게시물을 읽고 처리할 수 있는지 확인하는 것입니다.

루핑



단일 기사를 인쇄하는 모든 코드를 각 기사를 인쇄하는 루프로 대체할 것입니다. 복습을 위해 첫 번째 기사를 인쇄하는 코드는 다음과 같습니다.

    c := "`" + db.Db[0].Data.Posts[0].Mobiledoc + "`"

    un, err := strconv.Unquote(c)
    if err != nil {
        fmt.Println(err)
    }
    fmt.Printf("%v", un)

    var md Mobiledoc

    err = json.Unmarshal([]byte(un), &md)
    if err != nil {
        fmt.Println(err)
    }

    fmt.Printf("%#v", md)

    card := md.Cards[0][1]
    fmt.Printf("\n\ncard: %#v\n", card)

    bbb := card.(map[string]interface{})
    fmt.Println(bbb["markdown"])

이것의 대부분은 우리의 새로운 루프 안에 있을 것입니다.

    for i := 0; i < len(db.Db[0].Data.Posts); i++ {
        fmt.Println(db.Db[0].Data.Posts[i].Title)
        fmt.Println(db.Db[0].Data.Posts[i].Slug)
        fmt.Println(db.Db[0].Data.Posts[i].Status)
        fmt.Println(db.Db[0].Data.Posts[i].CreatedAt)
        fmt.Println(db.Db[0].Data.Posts[i].UpdatedAt)

        cc := "`" + db.Db[0].Data.Posts[i].Mobiledoc + "`"

        ucn, err := strconv.Unquote(cc)
        if err != nil {
            fmt.Println(err, ucn)
        }
        fmt.Printf("\n\n\n%v\n\n\n", ucn)

        var md Mobiledoc

        err = json.Unmarshal([]byte(ucn), &md)
        if err != nil {
            fmt.Println(err)
        }

        card := md.Cards[0][1]
        bbb := card.(map[string]interface{})

        fmt.Println(bbb["markdown"])
        }
    }

그리고 이번에 코드를 실행하면 많은 기사가 날아가는 것을 볼 수 있습니다! 즉, 오류가 발생할 때까지! invalid syntax 오류는 이것이 strconv.Unquote()의 문제임을 나타냅니다.

invalid syntax 

unexpected end of JSON input
panic: runtime error: index out of range [0] with length 0

goroutine 1 [running]:
main.main()
        /Users/steve/Code/ghost2hugo/main.go:214 +0x769
exit status 2

장애물



글쎄요, 우리 코드가 그렇게 충돌하게 만들 수는 없습니다! 문제를 자세히 살펴보고 문제를 해결할 수 있는지 살펴보겠습니다. 자, 이제 모든 디버깅 기술의 마스터입니다! fmt.Println를 추가하여 텍스트 덩어리를 출력합니다.

        fmt.Println(cc)

코드를 다시 실행하면 예상대로 충돌이 발생하지만 이번에는 문제 텍스트가 표시됩니다.

`{"version":"0.3.1","markups":[],"atoms":[],"cards":[["markdown",{"cardName":"card-markdown","markdown":"\n* Incresed title to 64 characters. Should be more then enough. \n * ics and other code work over at angstridden dot net tonight.\n\nALTER TABLE `posts` CHANGE `posttitle` `posttitle` VARCHAR( 64 ) NOT NULL\n\n\n"}]],"sections":[[10,0]],"ghostVersion":"3.0"}`

문제가 보이십니까? 예, 문자열 변환이 예상대로 작동하지 않는 원인이 되는 Markdown에 백틱이 있는 것 같습니다. 이 문제를 해결하기 위해 백틱을 다른 것으로 변경하기 위해 변환하기 전에 간단한 작업strings.ReplaceAll을 수행할 것입니다. 그런 다음 일반 텍스트를 얻기 위해 해당 프로세스를 되돌릴 수 있습니다. 백틱을 "%' "로 교체합니다.

        c := strings.ReplaceAll(db.Db[0].Data.Posts[i].Mobiledoc, "`", "%'")
        cc := "`" + c + "`"

"인용 해제"한 후 다른 항목strings.ReplaceAll을 실행하여 다시 변환할 수 있습니다.

        ucn = strings.ReplaceAll(ucn, "%'", "`")

다시 실행하면 또 다른 문제가 발생합니다!

---
Archives
archives-post
published
2007-07-01 09:46:18 +0000 UTC
2007-08-12 20:50:02 +0000 UTC
`{"version":"0.3.1","markups":[],"atoms":[],"cards":[],"sections":[[1,"p",[[0,[],0,""]]]],"ghostVersion":"3.0"}`
panic: runtime error: index out of range [0] with length 0

goroutine 1 [running]:
main.main()
        /Users/steve/Code/ghost2hugo/main.go:214 +0x7a6
exit status 2

아!

더 많은 장애물



이전 게시물의 순진한 구현이 우리를 물기 위해 돌아왔습니다! 우리는 카드가 존재한다고 가정했습니다.

        card := md.Cards[0][1]
        bbb := card.(map[string]interface{})

반환된 JSON을 보면 이를 확인할 수 있습니다.

{"version":"0.3.1","markups":[],"atoms":[],"cards":[],"sections":[[1,"p",[[0,[],0,""]]]],"ghostVersion":"3.0"}


이제 카드 필드가 비어 있는지 어떻게 확인합니까?! 나는 그것에 약간의 국수를 넣고 reflect.ValueOf().Len()를 사용하는 것이 가장 좋은 방법이라고 생각했습니다. 그러면 md.Cards의 길이를 확인하여 실제로 일부 데이터가 있는지 확인합니다.

        if reflect.ValueOf(md.Cards).Len() > 0 {
            card := md.Cards[0][1]
            bbb := card.(map[string]interface{})

            fmt.Println(bbb["markdown"])
        }

다시 실행하면 모든 게시물처럼 보이는 것을 얻습니다. 이상하게 보이는 최종 초안을 제외하고! 이것은 Markdown 카드가 없는 것으로 밝혀졌습니다. 이것뿐인가요? Markdown으로 변환하는 것이 고통스러울 수 있기 때문에 확실히 그렇게 되기를 바랍니다.

Questing
questing
draft
2019-08-23 21:26:44 +0000 UTC
2021-04-12 04:53:26 +0000 UTC
`{"version":"0.3.1","atoms":[],"cards":[["paywall",{}]],"markups":[["a",["href","https://shindakun.dev"]],["a",["href","https://dev.to/shindakun"]]],"sections":[[1,"p",[[0,[],0,"It's been quite sometime since I've posted anything here. I've done a bit of posting over on "],[0,[0],1,"shindakun.dev"],[0,[],0," and over on "],[0,[1],1,"DEV"],[0,[],0," which has been kind of nice. But, those don't really cover gaming at all. But, I updated the site recently and everyone once in a while I use the site to try something out for work and seeing an old post over and over was no good."]]],[1,"p",[[0,[],0,"I only seem to have a small sliver of time for gaming now. With everything else I want/need to get done there is only so much time. Heed this warning - don't get older! Just kidding, it's not so bad."]]],[1,"p",[[0,[],0,"My 5 year old hasn't been introduced into gaming much outside of some basic games she can play on her tablet. I have discovered that she enjoys watching me play the digital version of Warhammer Quest. Which is good since she's going to be getting a crash course in some more difficult board games sooner or later. I have a copy of the Gloomhaven digital board game and the boxed game (and expansion) but haven't actually event opened it yet. Maybe I should fix that this weekend..."]]],[10,0],[1,"p",[]]],"ghostVersion":"3.0"}`
json: cannot unmarshal string into Go struct field Mobiledoc.sections of type int
<nil>

마지막 줄에 언마샬링 문제도 있는 것 같습니다. 지금은 쉽게 고칠 수 있습니다. sections가 아닌 Mobiledoc를 사용하려면 struct [][]interface{}에서 [][]int를 업데이트하면 됩니다.

type Mobiledoc struct {
    Version string `json:"version"`
    Markups []interface{} `json:"markups"`
    Atoms []interface{} `json:"atoms"`
    Cards [][]interface{} `json:"cards"`
    Sections [][]interface{} `json:"sections"`
    GhostVersion string `json:"ghostVersion"`
}

다음번



우리는 지난 몇 개의 게시물에서 좋은 진전을 이루었습니다. 처음에는 필요한 것을 추출하는 것 같습니다. 약간의 리팩토링을 수행하고 현재 디버그 인쇄 문을 제거하고 변환기의 다음 부분을 준비할 준비가 된 것 같습니다.



이 게시물을 즐기십니까?


How about buying me a coffee?





신다쿤 / atlg


Dev.to에 올린 "Attempting to Learn Go" 게시물의 소스 저장소





Go 배우기 시도


여기에서 내가 작성하고 게시한 Go 학습 시도 게시물에 대해 작성한 코드를 찾을 수 있습니다.

포스트 색인



게시하다
암호



-

-

-

-

-

src

src

src

src

src

src

src

src

src

src

src

src

src

src

src

위 코드 참조





View on GitHub


코드 목록




package main

import (
    "encoding/json"
    "fmt"
    "io"
    "os"
    "reflect"
    "strconv"
    "strings"
    "time"
)

type GhostDatabase struct {
    Db []struct {
        Meta struct {
            ExportedOn int64 `json:"exported_on"`
            Version string `json:"version"`
        } `json:"meta"`
        Data struct {
            Posts []struct {
                ID string `json:"id"`
                UUID string `json:"uuid"`
                Title string `json:"title"`
                Slug string `json:"slug"`
                Mobiledoc string `json:"mobiledoc"`
                HTML string `json:"html"`
                CommentID string `json:"comment_id"`
                Plaintext string `json:"plaintext"`
                FeatureImage interface{} `json:"feature_image"`
                Featured int `json:"featured"`
                Type string `json:"type"`
                Status string `json:"status"`
                Locale interface{} `json:"locale"`
                Visibility string `json:"visibility"`
                EmailRecipientFilter string `json:"email_recipient_filter"`
                AuthorID string `json:"author_id"`
                CreatedAt time.Time `json:"created_at"`
                UpdatedAt time.Time `json:"updated_at"`
                PublishedAt time.Time `json:"published_at"`
                CustomExcerpt interface{} `json:"custom_excerpt"`
                CodeinjectionHead interface{} `json:"codeinjection_head"`
                CodeinjectionFoot interface{} `json:"codeinjection_foot"`
                CustomTemplate interface{} `json:"custom_template"`
                CanonicalURL interface{} `json:"canonical_url"`
            } `json:"posts"`
            PostsAuthors []struct {
                ID string `json:"id"`
                PostID string `json:"post_id"`
                AuthorID string `json:"author_id"`
                SortOrder int `json:"sort_order"`
            } `json:"posts_authors"`
            PostsMeta []interface{} `json:"posts_meta"`
            PostsTags []struct {
                ID string `json:"id"`
                PostID string `json:"post_id"`
                TagID string `json:"tag_id"`
                SortOrder int `json:"sort_order"`
            } `json:"posts_tags"`
            Roles []struct {
                ID string `json:"id"`
                Name string `json:"name"`
                Description string `json:"description"`
                CreatedAt time.Time `json:"created_at"`
                UpdatedAt time.Time `json:"updated_at"`
            } `json:"roles"`
            RolesUsers []struct {
                ID string `json:"id"`
                RoleID string `json:"role_id"`
                UserID string `json:"user_id"`
            } `json:"roles_users"`
            Settings []struct {
                ID string `json:"id"`
                Group string `json:"group"`
                Key string `json:"key"`
                Value string `json:"value"`
                Type string `json:"type"`
                Flags interface{} `json:"flags"`
                CreatedAt time.Time `json:"created_at"`
                UpdatedAt time.Time `json:"updated_at"`
            } `json:"settings"`
            Tags []struct {
                ID string `json:"id"`
                Name string `json:"name"`
                Slug string `json:"slug"`
                Description interface{} `json:"description"`
                FeatureImage interface{} `json:"feature_image"`
                ParentID interface{} `json:"parent_id"`
                Visibility string `json:"visibility"`
                OgImage interface{} `json:"og_image"`
                OgTitle interface{} `json:"og_title"`
                OgDescription interface{} `json:"og_description"`
                TwitterImage interface{} `json:"twitter_image"`
                TwitterTitle interface{} `json:"twitter_title"`
                TwitterDescription interface{} `json:"twitter_description"`
                MetaTitle interface{} `json:"meta_title"`
                MetaDescription interface{} `json:"meta_description"`
                CodeinjectionHead interface{} `json:"codeinjection_head"`
                CodeinjectionFoot interface{} `json:"codeinjection_foot"`
                CanonicalURL interface{} `json:"canonical_url"`
                AccentColor interface{} `json:"accent_color"`
                CreatedAt time.Time `json:"created_at"`
                UpdatedAt time.Time `json:"updated_at"`
            } `json:"tags"`
            Users []struct {
                ID string `json:"id"`
                Name string `json:"name"`
                Slug string `json:"slug"`
                Password string `json:"password"`
                Email string `json:"email"`
                ProfileImage string `json:"profile_image"`
                CoverImage interface{} `json:"cover_image"`
                Bio interface{} `json:"bio"`
                Website interface{} `json:"website"`
                Location interface{} `json:"location"`
                Facebook interface{} `json:"facebook"`
                Twitter interface{} `json:"twitter"`
                Accessibility string `json:"accessibility"`
                Status string `json:"status"`
                Locale interface{} `json:"locale"`
                Visibility string `json:"visibility"`
                MetaTitle interface{} `json:"meta_title"`
                MetaDescription interface{} `json:"meta_description"`
                Tour interface{} `json:"tour"`
                LastSeen time.Time `json:"last_seen"`
                CreatedAt time.Time `json:"created_at"`
                UpdatedAt time.Time `json:"updated_at"`
            } `json:"users"`
        } `json:"data"`
    } `json:"db"`
}

type Mobiledoc struct {
    Version string `json:"version"`
    Markups []interface{} `json:"markups"`
    Atoms []interface{} `json:"atoms"`
    Cards [][]interface{} `json:"cards"`
    Sections [][]interface{} `json:"sections"`
    GhostVersion string `json:"ghostVersion"`
}

func main() {
    fmt.Println("ghost2hugo")

    file, err := os.Open("shindakun-dot-net.ghost.2022-03-18-22-02-58.json")
    if err != nil {
        fmt.Println(err)
    }

    defer file.Close()

    b, err := io.ReadAll(file)
    if err != nil {
        fmt.Println(err)
    }

    var db GhostDatabase

    err = json.Unmarshal(b, &db)
    if err != nil {
        fmt.Println(err)
    }

    for i := 0; i < len(db.Db[0].Data.Posts); i++ {
        fmt.Println(db.Db[0].Data.Posts[i].Title)
        fmt.Println(db.Db[0].Data.Posts[i].Slug)
        fmt.Println(db.Db[0].Data.Posts[i].Status)
        fmt.Println(db.Db[0].Data.Posts[i].CreatedAt)
        fmt.Println(db.Db[0].Data.Posts[i].UpdatedAt)

        c := strings.ReplaceAll(db.Db[0].Data.Posts[i].Mobiledoc, "`", "%'")
        cc := "`" + c + "`"

        fmt.Println(cc)

        ucn, err := strconv.Unquote(cc)
        if err != nil {
            fmt.Println(err, ucn)
        }

        ucn = strings.ReplaceAll(ucn, "%'", "`")

        var md Mobiledoc

        err = json.Unmarshal([]byte(ucn), &md)
        if err != nil {
            fmt.Println(err)
        }

        if reflect.ValueOf(md.Cards).Len() > 0 {
            card := md.Cards[0][1]
            bbb := card.(map[string]interface{})

            fmt.Println(bbb["markdown"])
        }

        fmt.Println("---")
    }
}

좋은 웹페이지 즐겨찾기