On Mon, 11 Mar 2019 at 01:09, Roelof Wobben <r.wob...@home.nl> wrote:
> Op 10-3-2019 om 17:45 schreef Ben Coman: > > > > On Sun, 10 Mar 2019 at 23:40, Roelof Wobben <r.wob...@home.nl> wrote: > >> Op 10-3-2019 om 16:19 schreef Ben Coman: >> >> >> >> On Sun, 10 Mar 2019 at 17:55, Roelof Wobben <r.wob...@home.nl> wrote: >> >>> I could do something like this : >>> >>> getImages >>> | json numbers json2 | >>> json := NeoJSONReader >>> fromString: >>> (ZnEasy >>> get: >>> ' >>> https://www.rijksmuseum.nl/api/nl/collection?key=14OGzuak&format=json&type=schilderij&toppieces=True >>> ') >>> contents. >>> numbers := self class fromJSON: json >>> numbers do: [each | json := ......... >>> imageData = self class ??? >>> >> >> I'm not sure what "numbers" refers to. It seems a quite non-domain >> related identifier. >> To understand the domain, pasting the json contents of your link above >> into https://jsonformatter.curiousconcept.com/ >> and collapsing objects I see the structure is... >> >> <snip> > > Did you work through this example I provided? Please do so. > In a clean image... > >> Start with only your original code (which was good btw)... >> >> Paintings class >> fromJSON: json >> | instance artObjects | >> instance := self new. >> artObjects := json at: #artObjects. >> artObjects >> do: >> [ :eachArtObject | instance addPainting: (Painting >> fromJSON: eachArtObject) ]. >> ^ instance >> >> > except objectNumber(s) seem associated with each painting, so should be > stored within the painting object, as ADDED here... > > > Painting class >> fromJSON: json > > | instance | > instance := self new. > instance > objectNumber: (json at: #objectNumber); "<<<<<<<<ADDED" > title: (json at: #title); > painter: (json at: #principalOrFirstMaker); > imageUrl: ((json at: #webImage) at: #url). > ^ instance > > Evaluate the following in Playground... > collectionUrl := ' > https://www.rijksmuseum.nl/api/nl/collection?key=14OGzuak&format=json&type=schilderij&toppieces=True > '. > collectionJson := NeoJSONReader fromString: (ZnEasy get: > collectionUrl) contents. > paintings := Paintings fromJSON: collectionJson. > paintings inspect. > > then clean the DNU errors as they occur (i.e. click the <Create> button > shown by the debugger, and fill in as follows...) > when you save the methods, choose <Declare new instance variable>" > > Painting >> objectNumber: aString > objectNumber := aString > >> Painting >> title: aString >> title := aString >> >> Painting >> painter: aString >> painter := aString >> >> Painting >> imageUrl: aString >> imageUrl := aString >> >> Paintings >> addPainting: aPainting >> paintings := paintings ifNil: [ OrderedCollection new ]. >> paintings add: aPainting. >> >> and an inspector will appear showing a list of paintings, which you can >> drill down to a painting and see each has the expected data. >> Now just to round things off... >> >> Painting >> title >> ^ title >> >> Painting >> printOn: aStream >> super printOn: aStream. >> aStream << ' (' << self title << ')' >> >> to help distinguish each item in the Inspector. >> >> >> To extend the Playground code to download and display a painting, in >> Playground evaluate... >> >> painting := paintings first. >> imageResponse := ZnEasy get: painting imageUrl. >> image := ImageReadWriter formFromStream: imageResponse entity >> readStream. >> image inspect. >> >> Paintings >> first >> ^ paintings first >> >> Painting >> imageUrl >> ^ imageUrl >> >> and an inspector on the `image` variable displays the painting on the >> Morph tab. >> >> >> Now to mold the IDE to your domain... >> using Spotter to browser gtInspector* methods, a promising find is... >> AbstractFileReference>>gitInspectorJpegIn: >> from which I produced... >> >> Painting >> gtInspectorJpegIn: composite >> <gtInspectorPresentationOrder: 0> >> composite morph >> title: 'Painting'; >> display: [ ImageReadWriter formFromStream: self imageEntity readStream ] >> >> Then inspecting the `paintings` variable and drilling down to a painting >> pops up a DNU #imageEntity, which can be resolved by... >> >> Painting >> imageEntity >> ^ imageEntity ifNil: [ imageEntity := (ZnEasy get: self imageUrl) entity >> ]. >> >> and you get to see the painting shown in the Inspector. >> >> >> Now if I understand your question... "Do I need to make some more object >> to get this working..." >> I'd say... No. You only want one object for each painting. Once you have >> a painting object, it should handle all getting all further data it needs >> for itself. >> You don't want duplicate objects each having half of the data. >> >> >> can I for example name the function fromJson2 or fromJSONFromLink2 ? >>> >> >> By naming convention #fromJson: implies it sits on the class side. >> To get further data for an existing object you want an instance-side >> method, maybe named #getLink2Json. >> >> HTH, >> cheers -ben >> >> >> >> oke >> >> numbers should be the objectNumbers because for the rest I need them >> > > > > >> >> >> I use a instance variable called painting to hold the data. >> >> >> so I can change the call to get data for the painting to : >> >> Painting class >> fromJSON: json >> | instance | >> instance := self new. >> instance >> objectNumber: ((json at: #objectNumber). >> ^ instance >> >> >> so numbers should be a collection of 10 ObjectNumbers >> > > I'm presuming that 10 objectNumbers relate to 10 different paintings, > in which case, No, you should never need to deal with a collection of 10 > objectNumbers. > What you should have is a collection of painting-objects which know their > own objectNumber > and then iterate that collection sending each painting-object the message > "getLink2Json". > > > >> so I should use a loop to make a call to the second api call >> > > In Pharo OO approach, you don't "loop" on the "calls", > you "iterate" on the "objects" asking them to use their own data to do the > stuff they know how to do. > i.e. Let each object take care of itself. > > Which class is getImages defined on? That is really important to > understand your proposed solution. > I'm just presuming its defined on the class side of Paintings since your > are referring to the same URL as before. > >> >> getImages >> | json numbers | >> json := NeoJSONReader >> fromString: >> (ZnEasy >> get: >> ' >> https://www.rijksmuseum.nl/api/nl/collection?key=14OGzuak&format=json&type=schilderij&toppieces=True >> ') >> contents. >> numbers painting := self class fromJSON: json >> > > btw, it won't work with two identifiers "numbers painting" to the left of > the assignment symbol. Space here bad. > > > numbers do: [each | json := call to the second url.here I used >> each >> imageData = self class >> getLink2Json >> > json2 := call to the 3th url >> otherData := self class >> getLink3Json >> >> > > no :) the "self class" seems wrong. > getting extra data about a painting should be handled by the instance side > of its painting-object. > > > >> Then I can I hope on every json method fill in the data I need >> >> Do I understand you well >> > > I think not so well yet :) (or else I am missing something) > Keep trying. It will change the way you think about programming. > > Please work though the example I provided. > cheers -ben > > > > > I did and it worked the same as my code > Still I do not see how to use then the objectNumber in a second call to > the api > for example > > lets say we have only 1 objectNumber now > for example > > SK-C-5 > > then I need that one here : > https://www.rijksmuseum.nl/api/nl/collection/SK-C-5?key=[API_KEY]&format=json > so I see a json response of this : > > <snip> > where I at this moment need only artObjects -> makers -> name and artobject > -> title > > And I need to do that for all 10 > > But as far as I know I can only have one fromJson > > You can have as many Painting-class>>fromJsonXxxx methods as you like, but you only call one of them once per painting. This has nothing to do with Json and everything to do with your Painting-class>>fromJson method creating a new Painting-object, and you only want *one* Painting-object per Json-painting, so you can only call one. But actually, you don't need any Painting>>fromJSON:. Please delete it !!!! Then modify the other one as follows... Paintings class >> fromJSON: json | instance | instance := self new. (json at: #artObjects) do: [ :artObjectJson | |painting| painting := Painting new. painting objectNumber: (artObjectJson at: #objectNumber); title: (artObjectJson at: #title); painter: (artObjectJson at: #principalOrFirstMaker); imageUrl: ((artObjectJson at: #webImage) at: #url). instance addPainting: painting ]. ^ instance Does... collectionUrl := ' https://www.rijksmuseum.nl/api/nl/collection?key=14OGzuak&format=json&type=schilderij&toppieces=True '. json := NeoJSONReader fromString: (ZnEasy get: collectionUrl) contents. paintings := Paintings fromJSON: json. give you the same result as before? so how do I take care that the second one is called and parsed > and the right info is on the Painting object > > That is my question all the time > > As I said before... > What you should have is a collection of painting-objects which know their own objectNumber > and then iterate that collection sending each painting-object the message "getLink2Json". So more generically, add something like... Painting >> getMoreData "or a better name of your own" | url json artObjectJson | url := 'https://www.rijksmuseum.nl/api/nl/collection/' , objectNumber , '?key=[API_KEY]&format=json' Transcript crShow: 'Getting description from ', url. json := (NeoJSONReader fromString: (ZnEasy get: url) contents). artObjectJson := json at: 'artObject. description := artObjectJson at: 'description'. title := artObjectJson at: 'title'. Now in playground, variable paintings holds a collection 10 ten paintings. So lets ask each of them to get more data. paintings do: [ :painting | painting getMoreData ]. cheers -ben