On 5 December 2017 at 20:44, Sven Van Caekenberghe <s...@stfx.eu> wrote:
>
>
> > On 5 Dec 2017, at 13:33, Ben Coman <b...@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
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) 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

Reply via email to