On Sun, 10 Mar 2019 at 04:55, Roelof Wobben <r.wobben@home.nl> wrote:
Hello,
I try to make a app which displays images from a external api .
I was hoping I could do it with only 1 json parsing but to get the right size of images I need more then 1
Right now I have two classes with fromJson methods
Painting class >> fromJSON: json | instance | instance := self new. instance title: (json at: #title); painter: (json at: #principalOrFirstMaker); imageUrl: ((json at: #webImage) at: #url). ^ instance
Paintings class > fromJSON: json
fromJSON: json | instance artObjects | instance := self new. artObjects := json at: #artObjects. artObjects do: [ :eachArtObject | instance addPainting: (Painting fromJSON: eachArtObject) ]. ^ instance
but to get it working right , I have to do it like this :
Painting class >> fromJSON: json | instance | instance := self new. instance title: (json at: #objectNumber); ^ instance
but the problem is now I need a second call to this url :
https://www.rijksmuseum.nl/api/nl/collection/<<objectNumber>/tiles?key=[API_KEY]&format=json
and then need a new imageUrl out of it. and then have one object with objectNumber and the new url
Also I have to make a call to this url : https://www.rijksmuseum.nl/api/nl/collection/<<<objectNumber>>?key=[API_KEY]&format=json
and also get some data out of it so that a painting will be one object with the objectNumber, new imageurl and some data out of the last call
Do I need to make some more object to get this working or is there a way I can change the code I use now to get things working
Regards,
Roelof
Its hard to tell from your description. You say "the problem is now I need a second call" but you've not shown the code that does the calling, and you've not shown the first call, or where you are looping through multiple paintings (I'm guessing that is the requirement) You say "Do I need to make some more object", but are you referring to more Paintings objects or more Painting objects? So speaking only very generally, this might be implemented in two ways... A1. Request the json of paintings into a Paintings object A2 Loop that json requesting each individual painting json to fully initialized Painting object or... B1. Request the json of paintings into a Paintings object B2. Loop that json create empty Painting objects B3. Iterate those Painting objects with each one requesting its own json from the server, and can do multiple requests if necessary And btw, very very generally, if you see even a hint of one way to do it - do it that way first and see what insights arise from that to improve it. Particularly when exploring a new domain like an unfamiliar API, the usual approach is... 1. Make it work 2. Make it right 3. Make it fast Use whatever hackery you need to get step 1 done before moving to step 2, which you are inquiring about. And often you don't even need step 3. cheers -ben
On Sun, 10 Mar 2019 at 17:55, Roelof Wobben <r.wobben@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=s... ') 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... { "elapsedMilliseconds":0, "count":4782, "countFacets":{ "hasimage":4359, "ondisplay":748 }, "artObjects":[ + ] , "facets":[ + ] } where artObjects is an array with each art object like this==> { "links":{ "self":"https://www.rijksmuseum.nl/api/nl/collection/SK-A-3580", "web":"https://www.rijksmuseum.nl/nl/collectie/SK-A-3580" }, "id":"nl-SK-A-3580", "objectNumber":"SK-A-3580", "title":"De Singelbrug bij de Paleisstraat in Amsterdam", "hasImage":true, "principalOrFirstMaker":"George Hendrik Breitner", "longTitle":"De Singelbrug bij de Paleisstraat in Amsterdam, George Hendrik Breitner, 1898", "showImage":true, "permitDownload":true, "webImage":{ "guid":"cd15e2fa-b1f6-41f4-9e9e-c2ca87abcca3", "offsetPercentageX":0, "offsetPercentageY":0, "width":2880, "height":1897, "url":" https://lh3.googleusercontent.com/Bawo7r1nPZV6sJ4OHZJHdKV_4Ky59vquAR7KoUXcNZ... " }, "headerImage":{ "guid":"fef39f74-9783-44c9-acae-69eac3a76b01", "offsetPercentageX":0, "offsetPercentageY":0, "width":1920, "height":460, "url":" https://lh3.googleusercontent.com/jR6y5a8lFvgYe37WxLPQJZTjBAaBB6aIFYMsFw9gGP... " }, "productionPlaces":[ "Amsterdam" ] } So evaluating the following in Playground... collectionUrl := ' https://www.rijksmuseum.nl/api/nl/collection?key=14OGzuak&format=json&type=s... '. collectionJson := NeoJSONReader fromString: (ZnEasy get: collectionUrl) contents. paintings := Paintings fromJSON: collectionJson. paintings inspect. then cleaning the DNU errors as i went, starting with 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 Painting class >> fromJSON: json | instance | instance := self new. instance title: (json at: #title); painter: (json at: #principalOrFirstMaker); imageUrl: ((json at: #webImage) at: #url). ^ instance I added (roughly in order that each DNU occurred)... 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. I get an inspector on a list of paintings and can drill down to a painting and see each has the expected data, and just to round things off... Painting >> title ^ title Painting >> printOn: aStream super printOn: aStream. aStream << ' (' << self title << ')' helps distinguish each item in the Inspector. Now to extend the Playground code to download and display a painting, in Playground I evaluated... 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
On Sun, 10 Mar 2019 at 23:40, Roelof Wobben <r.wobben@home.nl> wrote:
Op 10-3-2019 om 16:19 schreef Ben Coman:
On Sun, 10 Mar 2019 at 17:55, Roelof Wobben <r.wobben@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=s... ') 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=s... '. 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=s... ') 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
On Mon, 11 Mar 2019 at 01:09, Roelof Wobben <r.wobben@home.nl> wrote:
Op 10-3-2019 om 17:45 schreef Ben Coman:
On Sun, 10 Mar 2019 at 23:40, Roelof Wobben <r.wobben@home.nl> wrote:
Op 10-3-2019 om 16:19 schreef Ben Coman:
On Sun, 10 Mar 2019 at 17:55, Roelof Wobben <r.wobben@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=s... ') 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=s... '. 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=s... ') 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=s... '. 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
Op 11-3-2019 om 00:03 schreef Ben Coman:
collectionUrl :=Â 'https://www.rijksmuseum.nl/api/nl/collection?key=14OGzuak&format=json&type=s...'. Â Â json := NeoJSONReader fromString: (ZnEasy get: collectionUrl) contents. Â Â paintings := Paintings fromJSON: json.
Thanks a lot , Ben I almost gave it up but I think I see a way to solve this The first part gives back exactly the same output as my old code. For the new one I have to do some trying but I think I can solve it Roelof
On Mon, 11 Mar 2019 at 14:35, Roelof Wobben <r.wobben@home.nl> wrote:
Op 11-3-2019 om 00:03 schreef Ben Coman:
collectionUrl := ' https://www.rijksmuseum.nl/api/nl/collection?key=14OGzuak&format=json&type=s... '. json := NeoJSONReader fromString: (ZnEasy get: collectionUrl) contents. paintings := Paintings fromJSON: json.
Thanks a lot , Ben
I almost gave it up but I think I see a way to solve this
The first part gives back exactly the same output as my old code. For the new one I have to do some trying but I think I can solve it
great !! Now it occurred to me that your approach seemed to be "based from applying functions to manipulate data that happens to be stored in an object", whereas you should invert that philosophy so you are "thinking from inside the object". What data do "I" have and what can "I" do with it. A great read that will help you is "A Mentoring Course in Smalltalk" http://www.lulu.com/au/en/shop/andres-valloud/a-mentoring-course-on-smalltal... cheers -ben
On Wed, 13 Mar 2019 at 00:43, Roelof Wobben <r.wobben@home.nl> wrote:
I did try to make this idea work but now im complete lost.
Right now the collection that should contain the objectNumbers is total empty anyone who can see where I went wrong.
I included my code so far.
A few things... !Paintings class methodsFor: 'instance creation' stamp: 'RoelofWobben 3/12/2019 17:26'! getImagesDataFromJSON: json | instance | instance := Painting new. (json at: #values) do: [ :artObjectJson | | painting | painting := Painting new. painting imageUrl: (json at: #name). instance addPainting: painting ]. ^ instance! ! You are adding a painting to a painting, which semantically makes no sense. i.e. where #addPainting: is sent to "instance" , that is holding a Painting. I would not expect your Painting class to have a method addPainting: Paintings should have that method. btw, Stop using "instance" as a variable name. Its as bad as variables named "a", "i", "t", "z" - it provides no semantic context. -------------------- Object subclass: #Paintings instanceVariableNames: 'paintings numbers' Paintings class instanceVariableNames: 'numbers paintings'! You've defined these variables on both the instance-side and class-side. I'll hazard a guess that you should delete the class-side definition. ---------------------------------- TBApplicationRootComponent initialize!Object subclass: #Painting instanceVariableNames: 'imageUrl' Why are you *not* storing objectNumber inside each Painting? What is the relationship between paintings and objectNumbers? Is it one-to-many or one-to-one? ------------------- !Paintings methodsFor: 'instance creation' stamp: 'RoelofWobben 3/11/2019 08:05'! initialize super initialize. numbers := OrderedCollection new! ! Why do you *not* initialize variable "paintings" to "OrderedCollection new" ? Aren't you dealing with a collection of paintings? ---------------- There is lots more confusing me here, so before going further, in a fresh new image, can you load NeoJSON and the attached fileout. Then in Playground do... collectionUrl := ' https://www.rijksmuseum.nl/api/nl/collection?key=14OGzuak&format=json&type=s... '. json := NeoJSONReader fromString: (ZnEasy get: collectionUrl) contents. paintings := Paintings fromJSON: json. paintings inspect. and then debug trace through that whole thing. Is that what you were trying to do? Or have I got the wrong end of the stick? cheers -ben
On Wed, 13 Mar 2019 at 02:10, Roelof Wobben <r.wobben@home.nl> wrote:
Op 12-3-2019 om 18:46 schreef Ben Coman:
Then in Playground do... collectionUrl := ' https://www.rijksmuseum.nl/api/nl/collection?key=14OGzuak&format=json&type=s... '. json := NeoJSONReader fromString: (ZnEasy get: collectionUrl) contents. paintings := Paintings fromJSON: json. paintings inspect.
and then debug trace through that whole thing. Is that what you were trying to do? Or have I got the wrong end of the stick?
cheers -ben
There is a one to one relationship between the objectNumber and a Painting
I do not use the imageUrl found on this url because it's to big .
okay. So I presume you want "artObject/webImage/url" ? { "artObject": { "webImage": { "url": " http://lh6.ggpht.com/wwx2vAS9DzFmmyeZefPjMtmCNOdjD80gvkXJcylloy40SiZOhdLHVdd... "
So what I try now is first put all the objectNumber in a collection and use that collection on a second url to fetch a image of the right size
Okay. I understand, but I am *still* coaching you to *not* do that. Rather than gathering a collection of dumb numbers and then creating new Painting objects from those, (which is awkward for joining the new data with the previous data) work with the Painting objects you already have. Add a new instance variables "webImageUrl" and "webImage" Then either Painting >> getMoreData |entity| ... webImageUrl := (artObjectJson at: 'webImage') at: 'url'. entity := (ZnEasy get: webImageUrl) entity. webImage := ImageReadWriter formFromStream: entity readStream. which may lock the UI for a moment downloading them all, or download lazily (slight variation on my previous imageEntity which doubles up on storage)... Painting >> getMoreData ... webImageUrl := (artObjectJson at: 'webImage') at: 'url'. Painting >> webImage |entity| webImageUrl ifNil: [^nil]. webImage ifNil: [ entity := (ZnEasy get: webImageUrl) entity. webImage := ImageReadWriter formFromStream: entity readStream]. ^ webImage Painting >> gtInspectorJpegIn: composite <gtInspectorPresentationOrder: 0> composite morph title: 'Painting'; display: [ self webImage ]
I hope im clear what I try to do in this step
yes it is. Please take my coaching and kill your collection of numbers. Keeping them keeps you stuck in old ways of thinking. So just kill it :) Once you've done that, alternatives will open up for you and you'll be on the path to a new way of thinking about programming. :) :)
so numbers should be a collection of objectNumbers
no.
and paintings a collection of painting with the info I need
yes, and objectNumber is part of the info of a painting.
so to recap
this one must give me a collection of objectNumbers : ' https://www.rijksmuseum.nl/api/nl/collection?key=14OGzuak&format=json&type=s... '.
no. it gives you a collection of paintings, of which objectNumber is one attribute.
and the objectNumbers I can use for this url :
https://www.rijksmuseum.nl/api/nl/collection/<one objectNumber/tiles?key=14OGzuak&format=json
and I do not store the objectNumber in Paintings because I do not use it to display it in a seaside project.
Regardless of whether you display it or not, objectNumber is supplied by the server "as an attribute belonging to painting" so store it inside your Painting objects. Then rather than Seaside asking a collection of dumb numbers for each JPEG to display it asks a collection of smart Painting objects for their JPEG to display (since they know their own objectNumber, they can get the JPEG themselves). cheers -ben On Wed, 13 Mar 2019 at 02:10, Roelof Wobben <r.wobben@home.nl> wrote:
Op 12-3-2019 om 18:46 schreef Ben Coman:
On Wed, 13 Mar 2019 at 00:43, Roelof Wobben <r.wobben@home.nl> wrote:
I did try to make this idea work but now im complete lost.
Right now the collection that should contain the objectNumbers is total empty anyone who can see where I went wrong.
I included my code so far.
A few things... !Paintings class methodsFor: 'instance creation' stamp: 'RoelofWobben 3/12/2019 17:26'! getImagesDataFromJSON: json | instance | instance := Painting new. (json at: #values) do: [ :artObjectJson | | painting | painting := Painting new. painting imageUrl: (json at: #name). instance addPainting: painting ]. ^ instance! !
You are adding a painting to a painting, which semantically makes no sense. i.e. where #addPainting: is sent to "instance" , that is holding a Painting.
I would not expect your Painting class to have a method addPainting: Paintings should have that method.
btw, Stop using "instance" as a variable name. Its as bad as variables named "a", "i", "t", "z" - it provides no semantic context.
-------------------- Object subclass: #Paintings instanceVariableNames: 'paintings numbers'
Paintings class instanceVariableNames: 'numbers paintings'!
You've defined these variables on both the instance-side and class-side. I'll hazard a guess that you should delete the class-side definition.
----------------------------------
TBApplicationRootComponent initialize!Object subclass: #Painting instanceVariableNames: 'imageUrl'
Why are you *not* storing objectNumber inside each Painting? What is the relationship between paintings and objectNumbers? Is it one-to-many or one-to-one?
------------------- !Paintings methodsFor: 'instance creation' stamp: 'RoelofWobben 3/11/2019 08:05'! initialize super initialize. numbers := OrderedCollection new! !
Why do you *not* initialize variable "paintings" to "OrderedCollection new" ? Aren't you dealing with a collection of paintings?
---------------- There is lots more confusing me here, so before going further, in a fresh new image, can you load NeoJSON and the attached fileout.
Then in Playground do... collectionUrl := ' https://www.rijksmuseum.nl/api/nl/collection?key=14OGzuak&format=json&type=s... '. json := NeoJSONReader fromString: (ZnEasy get: collectionUrl) contents. paintings := Paintings fromJSON: json. paintings inspect.
and then debug trace through that whole thing. Is that what you were trying to do? Or have I got the wrong end of the stick?
cheers -ben
Oke, I try to tell what I want
Right now I only want to fetch the objectNumber is a collection.
so I can use that in a later step.
There is a one to one relationship between the objectNumber and a Painting
I do not use the imageUrl found on this url because it's to big .
So what I try now is first put all the objectNumber in a collection and use that collection on a second url to fetch a image of the right size
I hope im clear what I try to do in this step
so numbers should be a collection of objectNumbers and paintings a collection of painting with the info I need
so to recap
this one must give me a collection of objectNumbers : ' https://www.rijksmuseum.nl/api/nl/collection?key=14OGzuak&format=json&type=s... '.
and the objectNumbers I can use for this url :
https://www.rijksmuseum.nl/api/nl/collection/<one objectNumber/tiles?key=14OGzuak&format=json
and I do not store the objectNumber in Paintings because I do not use it to display it in a seaside project.
Roelof
On Wed, 13 Mar 2019 at 04:59, Roelof Wobben <r.wobben@home.nl> wrote:
Op 11-3-2019 om 00:03 schreef Ben Coman:
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'.
hello Ben,
I think I almost see what you mean but still one problem
when doing this code :
collectionUrl := ' https://www.rijksmuseum.nl/api/nl/collection?key=14OGzuak&format=json&type=s... '. json := NeoJSONReader fromString: (ZnEasy get: collectionUrl) contents. paintings := Paintings fromJSON: json. paintings do: [:painting | painting getMoreData ]
here I see a error : instance of Paintings do not understand do:
I think we have to get the directory named paintings out of the object,
this seems to be working :
collectionUrl := ' https://www.rijksmuseum.nl/api/nl/collection?key=14OGzuak&format=json&type=s... '. json := NeoJSONReader fromString: (ZnEasy get: collectionUrl) contents. paintings := Paintings fromJSON: json. (paintings paintings) do: [:painting | painting getMoreData ]
You are right. An alternative fix is... Paintings >> do: aBlock ^ paintings do: aBlock cheers -ben
On Sun, 10 Mar 2019 at 23:19, Ben Coman <btc@openinworld.com> wrote:
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 ]
@all, can someone suggest a better #display: block that would shrink the image to the window size, and/or zooming. cheers -ben
participants (2)
-
Ben Coman -
Roelof Wobben