On 5 December 2017 at 20:44, Sven Van Caekenberghe <sven@stfx.eu> wrote:

> On 5 Dec 2017, at 13:33, Ben Coman <btc@openinworld.com> wrote:

> @sven, I started reading Enterprise Pharo a couple of hours ago.
> I don't quite get your section references. I presume you
> don't mean "chapter 11 Persisting Objects with Voyage, 11.3 Enhancing Storage"
> That seems off topic. And "chapter 4�� Zinc HTTP: The Client Side, 4.11 Headers"
> doesn't have a sub-part "3".

I meant 11.3 in this page https://ci.inria.fr/pharo-contribution/job/EnterprisePharoBook/lastSuccessfulBuild/artifact/book-result/Zinc-HTTP-Server/Zinc-HTTP-Server.html a section called 11.3. A Zinc Client.

> I guess part of what I'm interested in are patterns for hooking
> NeoJSON up to parse a REST response into objects to build a wrapper
> around a REST service. I see a chapter in Enterprise Pharo, which I'll
> get to that soon.�� Perhaps I was premature asking before reading that,
> but its good to have a few paths to explore.

Here is a recent example http://forum.world.st/Another-example-of-invoking-a-REST-JSON-web-service-resolving-User-Agent-strings-tt5017489.html


Thanks Sven.�� That helped a lot.�� ��I'd like to report success.
It may be useful to others to see how to progressively build up to parsing a Nested JSON REST


1. First parse the JSON into simple Dictionaries...

(ZnClient new��
url: 'https://bittrex.com/api/v1.1/public/getmarkets';
enforceHttpSuccess: true;
accept: ZnMimeType applicationJson;
contentReader: [ :entity | NeoJSONReader fromString: entity contents ];
get) inspect.

==>Dictionary(��
�� �� �� 'success' ==> true
�� �� �� 'message' ==> ''
�� �� �� 'result ' ==> an Array(a Dictionary('BaseCurrency'->'BTC' 'BaseCurrencyLong'->'Bitcoin')��
... a Dictionary('BaseCurrency'->'ETH' 'BaseCurrencyLong'->'Ethereum')��



2. Then parse the first level response into a real object...

Object subclass: #BittrexResponse
instanceVariableNames: 'success message result'
classVariableNames: ''
package: 'Bittrex'

(ZnClient new��
url: 'https://bittrex.com/api/v1.1/public/getmarkets';
enforceHttpSuccess: true;
accept: ZnMimeType applicationJson;
contentReader: [ :entity |��
(NeoJSONReader on: entity readStream)
mapInstVarsFor: BittrexResponse ;
�� �� �� �� nextAs: BittrexResponse ];
�� ��get) inspect.

==>BittrexResponse
�� �� �� success => true
�� �� �� message => ''��
�� �� �� result => an Array(a Dictionary('BaseCurrency'->'BTC' 'BaseCurrencyLong'->'Bitcoin')��
... a Dictionary('BaseCurrency'->'ETH' 'BaseCurrencyLong'->'Ethereum')��


Or alternatively...
(ZnClient new��
url: 'https://bittrex.com/api/v1.1/public/getmarkets';
enforceHttpSuccess: true;
accept: ZnMimeType applicationJson;
contentReader: [ :entity | |reader|
reader := (NeoJSONReader on: entity readStream).
reader for: BittrexResponse do: [:m|��
m mapInstVar: #success.
m mapInstVar: #message.
m mapInstVar: #result ].
�� �� �� reader nextAs: BittrexResponse ];
�� ��get) inspect.

==>BittrexResponse
�� �� �� success => true
�� �� �� message => ''��
�� �� �� result => an Array(a Dictionary('BaseCurrency'->'BTC' 'BaseCurrencyLong'->'Bitcoin')��
... a Dictionary('BaseCurrency'->'ETH' 'BaseCurrencyLong'->'Ethereum')��


3. Finally parse into real objects��the nested level holding the data you really want...

Object subclass: #Market
instanceVariableNames: 'MarketCurrency BaseCurrency MarketCurrencyLong BaseCurrencyLong MinTradeSize MarketName IsActive Created Notice IsSponsored LogoUrl'
classVariableNames: ''
package: 'Bittrex'

(ZnClient new��
enforceHttpSuccess: true;
accept: ZnMimeType applicationJson;
contentReader: [ :entity | |reader|
reader := (NeoJSONReader on: entity readStream).
reader for: BittrexResponse do: [:m|��
m mapInstVar: #success.
m mapInstVar: #message.
(m mapInstVar: #result) valueSchema: #ArrayOfMarkets].
reader for: #ArrayOfMarkets customDo: [ :mapping | mapping listOfElementSchema: Market ].
reader mapInstVarsFor: Market.��
�� �� �� reader nextAs: BittrexResponse ];
�� ��get) inspect.

==>BittrexResponse
�� �� �� success => true
�� �� �� message => ''��
�� �� �� result => an Array(a Market(LTC) a Market(DOGE) a Market(VTC) a Market(PPC) a Market(FTC) a Market(RDD)��
... Market(POWR) a Market(BTG) a Market(BTG) a Market(BTG) a Market(ADA) a Market(ENG) a Market(ENG))


WhooHoo!


A couple of things remaining:

* The instance variables of Market currently start with an upper-case to match the JSON fields.
�� Lower-casing the first letter breaks things.����
�� What strategies can be used to conform here to Smalltalk conventions?
�� Or is it easy enough to live with it?

* In various posts I've seen mention of a class-side method #neoJsonMapping:
�� ��but there is no explanation of this in��the Enterprise Book.����
�� ��How might #neoJsonMapping:��come into the picture for my use case above?

cheers -ben