├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── client.go ├── client_test.go ├── interface.go └── schema.go /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | *.test 24 | *.prof 25 | 26 | .idea/ 27 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | 3 | language: go 4 | go: 5 | - 1.9.x 6 | - 1.10.x 7 | - tip 8 | 9 | script: 10 | - go test -race -coverprofile=coverage.txt -covermode=atomic . 11 | 12 | after_success: 13 | - bash <(curl -s https://codecov.io/bash) 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Osamu TONOMORI 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # openbd 2 | 3 | [![Travis branch](https://img.shields.io/travis/osamingo/openbd/master.svg)](https://travis-ci.org/osamingo/openbd) 4 | [![codecov](https://codecov.io/gh/osamingo/openbd/branch/master/graph/badge.svg)](https://codecov.io/gh/osamingo/openbd) 5 | [![Go Report Card](https://goreportcard.com/badge/osamingo/openbd)](https://goreportcard.com/report/osamingo/openbd) 6 | [![codebeat badge](https://codebeat.co/badges/b8889073-90a0-4c69-805a-aa8f69361236)](https://codebeat.co/projects/github-com-osamingo-openbd-master) 7 | [![GoDoc](https://godoc.org/github.com/osamingo/openbd?status.svg)](https://godoc.org/github.com/osamingo/openbd) 8 | [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/osamingo/openbd/master/LICENSE) 9 | 10 | ## About 11 | 12 | - An [openbd](https://openbd.jp) client for Go. 13 | 14 | ## Install 15 | 16 | ```bash 17 | $ go get -u github.com/osamingo/openbd 18 | ``` 19 | 20 | ## Usage 21 | 22 | ```go 23 | package main 24 | 25 | import ( 26 | "fmt" 27 | 28 | "github.com/osamingo/openbd" 29 | ) 30 | 31 | func main() { 32 | 33 | cli, err := openbd.NewClientV1("https://api.openbd.jp", nil) 34 | if err != nil { 35 | panic(err) 36 | } 37 | 38 | isbn := "9784780802047" 39 | m, err := cli.Get(isbn) 40 | if err != nil { 41 | panic(err) 42 | } 43 | 44 | fmt.Println(m[isbn].Title()) 45 | } 46 | ``` 47 | 48 | ## License 49 | 50 | Released under the [MIT License](https://github.com/osamingo/openbd/blob/master/LICENSE). 51 | -------------------------------------------------------------------------------- /client.go: -------------------------------------------------------------------------------- 1 | package openbd 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "net/http" 7 | "net/url" 8 | "strings" 9 | ) 10 | 11 | // Client for openbd. 12 | type Client struct { 13 | URL *url.URL 14 | HTTPClient *http.Client 15 | } 16 | 17 | // NewClientV1 generates a client for openbd. 18 | func NewClientV1(host string, cli *http.Client) (Fetcher, error) { 19 | u, err := url.ParseRequestURI(host) 20 | if err != nil { 21 | return nil, err 22 | } 23 | u.Path = "/v1" 24 | if cli == nil { 25 | cli = http.DefaultClient 26 | } 27 | return Fetcher(&Client{ 28 | URL: u, 29 | HTTPClient: cli, 30 | }), nil 31 | } 32 | 33 | // Get book information by isbn. 34 | func (c *Client) Get(isbn ...string) (map[string]BookInformer, error) { 35 | if len(isbn) > 1e3 { 36 | return nil, fmt.Errorf("opendb: args length should be under 1,000 - length = %d", len(isbn)) 37 | } 38 | resp, err := c.HTTPClient.Get(c.URL.String() + "/get?isbn=" + strings.Join(isbn, ",")) 39 | if err != nil { 40 | return nil, err 41 | } 42 | defer resp.Body.Close() 43 | if resp.StatusCode != http.StatusOK { 44 | return nil, fmt.Errorf("opendb: faild to request - status code = %d", resp.StatusCode) 45 | } 46 | rs := make([]*Root, 0, len(isbn)) 47 | if err := json.NewDecoder(resp.Body).Decode(&rs); err != nil { 48 | return nil, err 49 | } 50 | m := make(map[string]BookInformer, len(rs)) 51 | for i := range rs { 52 | if rs[i] != nil { 53 | m[rs[i].Summary.Isbn] = BookInformer(rs[i]) 54 | } 55 | } 56 | return m, nil 57 | } 58 | -------------------------------------------------------------------------------- /client_test.go: -------------------------------------------------------------------------------- 1 | package openbd 2 | 3 | import "testing" 4 | 5 | const ( 6 | host = "https://api.openbd.jp" 7 | isbn = "9784780802047" 8 | ) 9 | 10 | func TestNewClient(t *testing.T) { 11 | cli, err := NewClientV1("", nil) 12 | if err == nil { 13 | t.Fatal("an error is nil") 14 | } 15 | cli, err = NewClientV1(host, nil) 16 | if err != nil { 17 | t.Fatal(err) 18 | } 19 | if cli == nil { 20 | t.Fatal("a client is nil") 21 | } 22 | } 23 | 24 | func TestClient_Get(t *testing.T) { 25 | cli, err := NewClientV1(host+"p", nil) 26 | if err != nil { 27 | t.Fatal(err) 28 | } 29 | _, err = cli.Get(isbn) 30 | if err == nil { 31 | t.Fatal("an error is nil") 32 | } 33 | cli, err = NewClientV1(host, nil) 34 | if err != nil { 35 | t.Fatal(err) 36 | } 37 | m, err := cli.Get("123") 38 | if err != nil { 39 | t.Fatal(err) 40 | } 41 | if bi, ok := m["123"]; ok { 42 | t.Fatalf("go %v, want nil", bi) 43 | } 44 | m, err = cli.Get(isbn) 45 | if err != nil { 46 | t.Fatal(err) 47 | } 48 | if len(m) == 0 { 49 | t.Fatal("a response is nil") 50 | } 51 | bi, ok := m[isbn] 52 | if !ok { 53 | t.Fatalf("not found - isbn = %s", isbn) 54 | } 55 | checkBookInformer(t, bi) 56 | 57 | // Parse check 58 | _, err = cli.Get("9784592187356") 59 | if err != nil { 60 | t.Fatal(err) 61 | } 62 | } 63 | 64 | func checkBookInformer(t *testing.T, bi BookInformer) { 65 | if bi.ISBN() != isbn { 66 | t.Errorf("got %s, want %s", bi.ISBN(), isbn) 67 | } 68 | if bi.Title() != "おにぎりレシピ101" { 69 | t.Errorf("got %s, want %s", bi.Title(), "おにぎりレシピ101") 70 | } 71 | if bi.Author() != "山田玲子/著 水野菜生/英訳" { 72 | t.Errorf("got %s, want %s", bi.Author(), "山田玲子/著 水野菜生/英訳") 73 | } 74 | if bi.Cover() != "https://cover.openbd.jp/9784780802047.jpg" { 75 | t.Errorf("got %s, want %s", bi.Cover(), "https://cover.openbd.jp/9784780802047.jpg") 76 | } 77 | if bi.PublishedAt() != "20140408" { 78 | t.Errorf("got %s, want %s", bi.PublishedAt(), "20140408") 79 | } 80 | if bi.Publisher() != "ポット出版" { 81 | t.Errorf("got %s, want %s", bi.Publisher(), "ポット出版") 82 | } 83 | if bi.Series() != "" { 84 | t.Errorf("got %s, want %s", bi.Series(), "") 85 | } 86 | if bi.Volume() != "" { 87 | t.Errorf("got %s, want %s", bi.Volume(), "") 88 | } 89 | if bi.ShortDescription() != "海外でも人気の日本のソウルフード、おにぎり。クッキングアドバイザー・山田玲子が考えた101のレシピを英訳付きでご紹介します。" { 90 | t.Errorf("got %s, want %s", bi.ShortDescription(), "海外でも人気の日本のソウルフード、おにぎり。クッキングアドバイザー・山田玲子が考えた101のレシピを英訳付きでご紹介します。") 91 | } 92 | if bi.Description() != "101人いれば、101通り、好みのおにぎりがあります。\nマイおにぎりを作ってもらうためのヒントになればと、クッキングアドバイザー・山田玲子が101のおにぎりレシピを考えました。全文英訳付き。\n日本のソウルフード、easy、simple、healthyなおにぎりは海外でも人気です。\n外国の方へのプレゼントなど、小さな外交がこの本から始まります。\n\nOnigiri—a healthy fast food—is the soul food of the Japanese. Although it may not be as widely recognized as sushi, onigiri is synonymous with the phrase “taste of home,” and is a staple of Japanese comfort food. Its simplicity—just combining rice and toppings—offers endless possibilities without borders. The portable onigiri can be served in all kinds of situations. It’s perfect for bento lunch, as a light snack, or even as party food. \nReiko Yamada’s 101 simple and easy riceball (onigiri) recipes include mixed, grilled, sushi-style onigiri and more! This cookbook is a perfect introduction to the art of onigiri-making, filled with unique recipes that are bound to inspire your Japanese culinary creativity. Pick up a copy, and you’ll become an onigiri expert in no time!\n\n" { 93 | t.Errorf("got %s, want %s", bi.Description(), "101人いれば、101通り、好みのおにぎりがあります。\nマイおにぎりを作ってもらうためのヒントになればと、クッキングアドバイザー・山田玲子が101のおにぎりレシピを考えました。全文英訳付き。\n日本のソウルフード、easy、simple、healthyなおにぎりは海外でも人気です。\n外国の方へのプレゼントなど、小さな外交がこの本から始まります。\n\nOnigiri—a healthy fast food—is the soul food of the Japanese. Although it may not be as widely recognized as sushi, onigiri is synonymous with the phrase “taste of home,” and is a staple of Japanese comfort food. Its simplicity—just combining rice and toppings—offers endless possibilities without borders. The portable onigiri can be served in all kinds of situations. It’s perfect for bento lunch, as a light snack, or even as party food. \nReiko Yamada’s 101 simple and easy riceball (onigiri) recipes include mixed, grilled, sushi-style onigiri and more! This cookbook is a perfect introduction to the art of onigiri-making, filled with unique recipes that are bound to inspire your Japanese culinary creativity. Pick up a copy, and you’ll become an onigiri expert in no time!\n\n") 94 | } 95 | if bi.JBPADescription() != "" { 96 | t.Errorf("got %s, want %s", bi.JBPADescription(), "") 97 | } 98 | if bi.TableOfContents() != "はじめに INTRODUCTION ……002\nこの本の使い方 HOW TO USE THIS COOKBOOK……002\nご飯の炊き方 HOW TO COOK RICE ……008\n塩のこと ALL ABOUT SALT ……010\nおにぎりのにぎり方 HOW TO MAKE ONIGIRI ……012\nおにぎりと具材の相性 ONIGIRI COMBINATIONS……014\nのりの使い方 HOW TO USE NORI SEAWEED ……016\n\n1. 中に入れる FILL……019\n2. 混ぜる MIX……037\n3. 炊き込む/焼く TAKIKOMI / GRILL……067\n4. のせる/つつむ SUSHI-STYLE / WRAP……085\n\nおかずレシピ OKAZU RECIPE……106\nおにぎりを冷凍保存 HOW TO KEEP LEFTOVER ONIGIRI ……113\nおにぎりをお弁当に詰める HOW TO PACK A BENTO ……104\nINGREDIENT GLOSSARY ……116\nこの本で使用したもの PRODUCT LIST ……120\nプロフィール PROFILE……121\nおわりに CLOSING ……122" { 99 | t.Errorf("got %s, want %s", bi.TableOfContents(), "はじめに INTRODUCTION ……002\nこの本の使い方 HOW TO USE THIS COOKBOOK……002\nご飯の炊き方 HOW TO COOK RICE ……008\n塩のこと ALL ABOUT SALT ……010\nおにぎりのにぎり方 HOW TO MAKE ONIGIRI ……012\nおにぎりと具材の相性 ONIGIRI COMBINATIONS……014\nのりの使い方 HOW TO USE NORI SEAWEED ……016\n\n1. 中に入れる FILL……019\n2. 混ぜる MIX……037\n3. 炊き込む/焼く TAKIKOMI / GRILL……067\n4. のせる/つつむ SUSHI-STYLE / WRAP……085\n\nおかずレシピ OKAZU RECIPE……106\nおにぎりを冷凍保存 HOW TO KEEP LEFTOVER ONIGIRI ……113\nおにぎりをお弁当に詰める HOW TO PACK A BENTO ……104\nINGREDIENT GLOSSARY ……116\nこの本で使用したもの PRODUCT LIST ……120\nプロフィール PROFILE……121\nおわりに CLOSING ……122") 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /interface.go: -------------------------------------------------------------------------------- 1 | package openbd 2 | 3 | type ( 4 | Fetcher interface { 5 | Get(isbn ...string) (map[string]BookInformer, error) 6 | } 7 | BookInformer interface { 8 | ISBN() string 9 | Title() string 10 | Author() string 11 | Cover() string 12 | PublishedAt() string 13 | Publisher() string 14 | Series() string 15 | Volume() string 16 | ShortDescription() string 17 | Description() string 18 | JBPADescription() string 19 | TableOfContents() string 20 | } 21 | ) 22 | -------------------------------------------------------------------------------- /schema.go: -------------------------------------------------------------------------------- 1 | package openbd 2 | 3 | type ( 4 | Audience struct { 5 | AudienceCode string `json:"AudienceCode,omitempty"` 6 | AudienceCodeValue string `json:"AudienceCodeValue,omitempty"` 7 | } 8 | 9 | Author struct { 10 | Dokujikubun string `json:"dokujikubun"` 11 | Listseq float64 `json:"listseq"` 12 | } 13 | 14 | CollateralDetail struct { 15 | SupportingResource []SupportingResource `json:"SupportingResource,omitempty"` 16 | TextContent []TextContent `json:"TextContent,omitempty"` 17 | } 18 | 19 | Collection struct { 20 | CollectionSequence *CollectionSequence `json:"CollectionSequence,omitempty"` 21 | Collection string `json:"Collection,omitempty"` 22 | TitleDetail struct { 23 | TitleElement []*TitleElement `json:"TitleElement,omitempty"` 24 | Title string `json:"Title,omitempty"` 25 | } `json:"TitleDetail,omitempty"` 26 | } 27 | 28 | CollectionSequence struct { 29 | CollectionSequenceNumber string `json:"CollectionSequenceNumber,omitempty"` 30 | CollectionSequence string `json:"CollectionSequence,omitempty"` 31 | } 32 | 33 | Contributor struct { 34 | BiographicalNote string `json:"BiographicalNote,omitempty"` 35 | ContributorRole []string `json:"ContributorRole,omitempty"` 36 | PersonName *PersonName `json:"PersonName,omitempty"` 37 | SequenceNumber string `json:"SequenceNumber,omitempty"` 38 | } 39 | 40 | DescriptiveDetail struct { 41 | Audience []Audience `json:"Audience,omitempty"` 42 | Collection *Collection `json:"Collection,omitempty"` 43 | Contributor []Contributor `json:"Contributor,omitempty"` 44 | Extent []Extent `json:"Extent,omitempty"` 45 | Language []Language `json:"Language,omitempty"` 46 | Measure []Measure `json:"Measure,omitempty"` 47 | ProductComposition string `json:"ProductComposition,omitempty"` 48 | ProductForm string `json:"ProductForm,omitempty"` 49 | ProductFormDetail string `json:"ProductFormDetail,omitempty"` 50 | ProductPart []ProductPart `json:"ProductPart,omitempty"` 51 | Subject []Subject `json:"Subject,omitempty"` 52 | TitleDetail *TitleDetail `json:"TitleDetail,omitempty"` 53 | } 54 | 55 | Extent struct { 56 | Extent string `json:"Extent,omitempty"` 57 | ExtentUnit string `json:"ExtentUnit,omitempty"` 58 | ExtentValue string `json:"ExtentValue,omitempty"` 59 | } 60 | 61 | Hanmoto struct { 62 | Author []Author `json:"author,omitempty"` 63 | Bessoushiryou string `json:"bessoushiryou,omitempty"` 64 | Bikoutrc string `json:"bikoutrc,omitempty"` 65 | Datecreated string `json:"datecreated,omitempty"` 66 | Datejuuhanyotei string `json:"datejuuhanyotei,omitempty"` 67 | Datemodified string `json:"datemodified"` 68 | Dateshuppan string `json:"dateshuppan,omitempty"` 69 | Datezeppan string `json:"datezeppan,omitempty"` 70 | Dokushakakikomi string `json:"dokushakakikomi,omitempty"` 71 | Dokushakakikomipagesuu float64 `json:"dokushakakikomipagesuu,omitempty"` 72 | Furoku float64 `json:"furoku,omitempty"` 73 | Furokusonota string `json:"furokusonota,omitempty"` 74 | Gatsugougousuu string `json:"gatsugougousuu,omitempty"` 75 | Genrecodetrc float64 `json:"genrecodetrc,omitempty"` 76 | Genrecodetrcjidou float64 `json:"genrecodetrcjidou,omitempty"` 77 | Genshomei string `json:"genshomei,omitempty"` 78 | Han string `json:"han,omitempty"` 79 | Hanmotokarahitokoto string `json:"hanmotokarahitokoto,omitempty"` 80 | Hastameshiyomi bool `json:"hastameshiyomi,omitempty"` 81 | Jushoujouhou string `json:"jushoujouhou,omitempty"` 82 | Jyuhan []Jyuhan `json:"jyuhan,omitempty"` 83 | Kaisetsu105w string `json:"kaisetsu105w,omitempty"` 84 | Kankoukeitai string `json:"kankoukeitai,omitempty"` 85 | Kanrensho string `json:"kanrensho,omitempty"` 86 | Kanrenshoisbn string `json:"kanrenshoisbn,omitempty"` 87 | Kubunhanbai bool `json:"kubunhanbai,omitempty"` 88 | Lanove bool `json:"lanove,omitempty"` 89 | Maegakinado string `json:"maegakinado,omitempty"` 90 | Ndccode string `json:"ndccode,omitempty"` 91 | Obinaiyou string `json:"obinaiyou,omitempty"` 92 | Reviews []Reviews `json:"reviews,omitempty"` 93 | Rubynoumu bool `json:"rubynoumu,omitempty"` 94 | Ruishokyougousho string `json:"ruishokyougousho,omitempty"` 95 | Sonotatokkijikou string `json:"sonotatokkijikou,omitempty"` 96 | Toji string `json:"toji,omitempty"` 97 | Tsuiki string `json:"tsuiki,omitempty"` 98 | Zaiko float64 `json:"zaiko,omitempty"` 99 | Zasshicode string `json:"zasshicode,omitempty"` 100 | } 101 | 102 | Imprint struct { 103 | ImprintIdentifier []ImprintIdentifier `json:"ImprintIdentifier,omitempty"` 104 | ImprintName string `json:"ImprintName,omitempty"` 105 | } 106 | 107 | ImprintIdentifier struct { 108 | IDValue string `json:"IDValue,omitempty"` 109 | ImprintID string `json:"ImprintID,omitempty"` 110 | } 111 | 112 | Jyuhan struct { 113 | Comment string `json:"comment,omitempty"` 114 | Ctime string `json:"ctime,omitempty"` 115 | Date string `json:"date"` 116 | Suri float64 `json:"suri,omitempty"` 117 | } 118 | 119 | Language struct { 120 | CountryCode string `json:"CountryCode,omitempty"` 121 | LanguageCode string `json:"LanguageCode,omitempty"` 122 | LanguageRole string `json:"LanguageRole,omitempty"` 123 | } 124 | 125 | Measure struct { 126 | Measure string `json:"Measure,omitempty"` 127 | MeasureUnitCode string `json:"MeasureUnitCode,omitempty"` 128 | Measurement string `json:"Measurement,omitempty"` 129 | } 130 | 131 | Onix struct { 132 | CollateralDetail *CollateralDetail `json:"CollateralDetail,omitempty"` 133 | DescriptiveDetail *DescriptiveDetail `json:"DescriptiveDetail,omitempty"` 134 | Notification string `json:"Notification,omitempty"` 135 | ProductIdentifier *ProductIdentifier `json:"ProductIdentifier,omitempty"` 136 | ProductSupply *ProductSupply `json:"ProductSupply,omitempty"` 137 | PublishingDetail *PublishingDetail `json:"PublishingDetail,omitempty"` 138 | RecordReference string `json:"RecordReference,omitempty"` 139 | } 140 | 141 | PersonName struct { 142 | Collationkey string `json:"collationkey,omitempty"` 143 | Content string `json:"content,omitempty"` 144 | } 145 | 146 | Price struct { 147 | CurrencyCode string `json:"CurrencyCode,omitempty"` 148 | PriceAmount string `json:"PriceAmount,omitempty"` 149 | PriceDate []PriceDate `json:"PriceDate,omitempty"` 150 | Price string `json:"Price,omitempty"` 151 | } 152 | 153 | PriceDate struct { 154 | Date string `json:"Date,omitempty"` 155 | Price string `json:"Price,omitempty"` 156 | PriceDateRole string `json:"PriceDateRole,omitempty"` 157 | } 158 | 159 | ProductIdentifier struct { 160 | IDValue string `json:"IDValue,omitempty"` 161 | ProductID string `json:"ProductID,omitempty"` 162 | } 163 | 164 | ProductPart struct { 165 | NumberOfItemsOfThisForm string `json:"NumberOfItemsOfThisForm,omitempty"` 166 | ProductForm string `json:"ProductForm,omitempty"` 167 | ProductFormDescription string `json:"ProductFormDescription,omitempty"` 168 | } 169 | 170 | ProductSupply struct { 171 | SupplyDetail *SupplyDetail `json:"SupplyDetail,omitempty"` 172 | } 173 | 174 | Publisher struct { 175 | PublisherIdentifier []PublisherIdentifier `json:"PublisherIdentifier,omitempty"` 176 | PublisherName string `json:"PublisherName,omitempty"` 177 | PublishingRole string `json:"PublishingRole,omitempty"` 178 | } 179 | 180 | PublisherIdentifier struct { 181 | IDValue string `json:"IDValue,omitempty"` 182 | PublisherID string `json:"PublisherID,omitempty"` 183 | } 184 | 185 | PublishingDate struct { 186 | Date string `json:"Date,omitempty"` 187 | PublishingDateRole string `json:"PublishingDateRole,omitempty"` 188 | } 189 | 190 | PublishingDetail struct { 191 | Imprint *Imprint `json:"Imprint,omitempty"` 192 | Publisher *Publisher `json:"Publisher,omitempty"` 193 | PublishingDate []PublishingDate `json:"PublishingDate,omitempty"` 194 | } 195 | 196 | ResourceVersion struct { 197 | ResourceForm string `json:"ResourceForm,omitempty"` 198 | ResourceLink string `json:"ResourceLink,omitempty"` 199 | ResourceVersionFeature []interface{} `json:"ResourceVersionFeature,omitempty"` 200 | } 201 | 202 | ReturnsConditions struct { 203 | ReturnsCode string `json:"ReturnsCode,omitempty"` 204 | } 205 | 206 | Reviews struct { 207 | Appearance string `json:"appearance,omitempty"` 208 | Choyukan string `json:"choyukan,omitempty"` 209 | Han string `json:"han,omitempty"` 210 | KubunId float64 `json:"kubun_id,omitempty"` 211 | Link string `json:"link,omitempty"` 212 | PostUser string `json:"post_user,omitempty"` 213 | Reviewer string `json:"reviewer,omitempty"` 214 | Source string `json:"source,omitempty"` 215 | SourceId float64 `json:"source_id,omitempty"` 216 | } 217 | 218 | Root struct { 219 | Hanmoto *Hanmoto `json:"hanmoto,omitempty"` 220 | Onix *Onix `json:"onix,omitempty"` 221 | Summary *Summary `json:"summary,omitempty"` 222 | } 223 | 224 | Subject struct { 225 | MainSubject string `json:"MainSubject,omitempty"` 226 | SubjectCode string `json:"SubjectCode,omitempty"` 227 | SubjectHeadingText string `json:"SubjectHeadingText,omitempty"` 228 | SubjectSchemeIdentifier string `json:"SubjectSchemeIdentifier,omitempty"` 229 | } 230 | 231 | Subtitle struct { 232 | Collationkey string `json:"collationkey,omitempty"` 233 | Content string `json:"content,omitempty"` 234 | } 235 | 236 | Summary struct { 237 | Author string `json:"author,omitempty"` 238 | Cover string `json:"cover,omitempty"` 239 | Isbn string `json:"isbn,omitempty"` 240 | Pubdate string `json:"pubdate,omitempty"` 241 | Publisher string `json:"publisher,omitempty"` 242 | Series string `json:"series,omitempty"` 243 | Title string `json:"title,omitempty"` 244 | Volume string `json:"volume,omitempty"` 245 | } 246 | 247 | SupplyDetail struct { 248 | Price []Price `json:"Price,omitempty"` 249 | ProductAvailability string `json:"ProductAvailability,omitempty"` 250 | ReturnsConditions *ReturnsConditions `json:"ReturnsConditions,omitempty"` 251 | } 252 | 253 | SupportingResource struct { 254 | ContentAudience string `json:"ContentAudience,omitempty"` 255 | ResourceContent string `json:"ResourceContent,omitempty"` 256 | ResourceMode string `json:"ResourceMode,omitempty"` 257 | ResourceVersion []ResourceVersion `json:"ResourceVersion,omitempty"` 258 | } 259 | 260 | TextContent struct { 261 | ContentAudience string `json:"ContentAudience,omitempty"` 262 | Text string `json:"Text,omitempty"` 263 | TextType string `json:"TextType,omitempty"` 264 | } 265 | 266 | TitleDetail struct { 267 | TitleElement *TitleElement `json:"TitleElement,omitempty"` 268 | Title string `json:"Title,omitempty"` 269 | } 270 | 271 | TitleElement struct { 272 | Subtitle *Subtitle `json:"Subtitle,omitempty"` 273 | TitleElementLevel string `json:"TitleElementLevel,omitempty"` 274 | TitleText *TitleText `json:"TitleText,omitempty"` 275 | } 276 | 277 | TitleText struct { 278 | Collationkey string `json:"collationkey,omitempty"` 279 | Content string `json:"content,omitempty"` 280 | } 281 | ) 282 | 283 | func (r *Root) ISBN() string { 284 | return r.Summary.Isbn 285 | } 286 | 287 | func (r *Root) Title() string { 288 | return r.Summary.Title 289 | } 290 | 291 | func (r *Root) Author() string { 292 | return r.Summary.Author 293 | } 294 | 295 | func (r *Root) Cover() string { 296 | return r.Summary.Cover 297 | } 298 | 299 | func (r *Root) PublishedAt() string { 300 | return r.Summary.Pubdate 301 | } 302 | 303 | func (r *Root) Publisher() string { 304 | return r.Summary.Publisher 305 | } 306 | 307 | func (r *Root) Series() string { 308 | return r.Summary.Series 309 | } 310 | 311 | func (r *Root) Volume() string { 312 | return r.Summary.Volume 313 | } 314 | 315 | func (r *Root) ShortDescription() string { 316 | if r.Onix == nil { 317 | return "" 318 | } 319 | if r.Onix.CollateralDetail == nil { 320 | return "" 321 | } 322 | for i := range r.Onix.CollateralDetail.TextContent { 323 | if r.Onix.CollateralDetail.TextContent[i].TextType == "02" { 324 | return r.Onix.CollateralDetail.TextContent[i].Text 325 | } 326 | } 327 | return "" 328 | } 329 | 330 | func (r *Root) Description() string { 331 | if r.Onix == nil { 332 | return "" 333 | } 334 | if r.Onix.CollateralDetail == nil { 335 | return "" 336 | } 337 | for i := range r.Onix.CollateralDetail.TextContent { 338 | if r.Onix.CollateralDetail.TextContent[i].TextType == "03" { 339 | return r.Onix.CollateralDetail.TextContent[i].Text 340 | } 341 | } 342 | return "" 343 | } 344 | 345 | func (r *Root) JBPADescription() string { 346 | if r.Onix == nil { 347 | return "" 348 | } 349 | if r.Onix.CollateralDetail == nil { 350 | return "" 351 | } 352 | for i := range r.Onix.CollateralDetail.TextContent { 353 | if r.Onix.CollateralDetail.TextContent[i].TextType == "23" { 354 | return r.Onix.CollateralDetail.TextContent[i].Text 355 | } 356 | } 357 | return "" 358 | } 359 | 360 | func (r *Root) TableOfContents() string { 361 | if r.Onix == nil { 362 | return "" 363 | } 364 | if r.Onix.CollateralDetail == nil { 365 | return "" 366 | } 367 | for i := range r.Onix.CollateralDetail.TextContent { 368 | if r.Onix.CollateralDetail.TextContent[i].TextType == "04" { 369 | return r.Onix.CollateralDetail.TextContent[i].Text 370 | } 371 | } 372 | return "" 373 | } 374 | --------------------------------------------------------------------------------