How to query a JSON

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

How to query a JSON

Pharo Smalltalk Users mailing list
Hello,

is there a way to query a JSON with a path (JSONPath or some custom format)?

I want to query an API and collect the JSON responses, which I need to iterate over to extract some data. Modelling the JSON structure as classes would be too much overhead, I think. I just want to collect some values...

Thanks in advance,
Marc
Reply | Threaded
Open this post in threaded view
|

Re: How to query a JSON

Sven Van Caekenberghe-2
Marc,

> On 24 May 2017, at 16:20, Marc Hanisch via Pharo-users <[hidden email]> wrote:

> Hello,
>
> is there a way to query a JSON with a path (JSONPath or some custom format)?
>
> I want to query an API and collect the JSON responses, which I need to iterate over to extract some data. Modelling the JSON structure as classes would be too much overhead, I think. I just want to collect some values...
>
> Thanks in advance,
> Marc

Normally, when you use the NeoJSON package and you don't do any mapping, you get Dictionaries and Arrays back.

There is however also something called NeoJSONObject, a Dictionary subclass that has some API that is quite fluent and that does include path style access.

To get started, use NeoJSONObject class>>#fromString: as parser.

Here is the class comment:

===
I am NeoJSONObject.
I am a Dictionary.

I behave more like a JavaScript object. I return nil for missing keys. I allow any property to be read or set by using a normal accessor message.

The following are equivalent:

        self foo.
        self at: #foo.

As are the following

        self foo: 1.
        self at: #foo put: 1.
       
Except that in the first case, self is returned.

I can optionally be used by NeoJSONReader as mapClass (see #mapClass:).

For output, I act just like my superclass (it is thus not necessary to do any conversions).

Example:

        NeoJSONObject fromString: '{"foo":1,"bar":-2}'.
        NeoJSONObject new foo: 1; bar: -2.
        { #x -> 100. #y -> 200 } as: NeoJSONObject.
        (NeoJSONObject new data: (NeoJSONObject new id: #sensor1; value: 37.5)) asString.

I use JSON as my printed representation. To convert me to JSON, use #printString or #asString.

Additionally, I support path access for nested instances of me, using #atPath: and #atPath:put:

The first is special because it returns nil as soon as a key is missing. The second is special because it creates extra levels (instances of me) as needed to follow the path of keys.

        NeoJSONObject new atPath: #(one two three) put: 42; yourself.
        NeoJSONObject new atPath: #(one two three) put: 42; atPath: #(one two three).
===

HTH,

Sven



Reply | Threaded
Open this post in threaded view
|

Re: How to query a JSON

Pharo Smalltalk Users mailing list
Hello Sven, 

Thanks for that hint! It looks like exactly what I need ☺️

Best regards, 
Marc

Am 24.05.2017 16:38 schrieb "Sven Van Caekenberghe" <[hidden email]>:
Marc,

> On 24 May 2017, at 16:20, Marc Hanisch via Pharo-users <[hidden email]> wrote:

> Hello,
>
> is there a way to query a JSON with a path (JSONPath or some custom format)?
>
> I want to query an API and collect the JSON responses, which I need to iterate over to extract some data. Modelling the JSON structure as classes would be too much overhead, I think. I just want to collect some values...
>
> Thanks in advance,
> Marc

Normally, when you use the NeoJSON package and you don't do any mapping, you get Dictionaries and Arrays back.

There is however also something called NeoJSONObject, a Dictionary subclass that has some API that is quite fluent and that does include path style access.

To get started, use NeoJSONObject class>>#fromString: as parser.

Here is the class comment:

===
I am NeoJSONObject.
I am a Dictionary.

I behave more like a JavaScript object. I return nil for missing keys. I allow any property to be read or set by using a normal accessor message.

The following are equivalent:

        self foo.
        self at: #foo.

As are the following

        self foo: 1.
        self at: #foo put: 1.

Except that in the first case, self is returned.

I can optionally be used by NeoJSONReader as mapClass (see #mapClass:).

For output, I act just like my superclass (it is thus not necessary to do any conversions).

Example:

        NeoJSONObject fromString: '{"foo":1,"bar":-2}'.
        NeoJSONObject new foo: 1; bar: -2.
        { #x -> 100. #y -> 200 } as: NeoJSONObject.
        (NeoJSONObject new data: (NeoJSONObject new id: #sensor1; value: 37.5)) asString.

I use JSON as my printed representation. To convert me to JSON, use #printString or #asString.

Additionally, I support path access for nested instances of me, using #atPath: and #atPath:put:

The first is special because it returns nil as soon as a key is missing. The second is special because it creates extra levels (instances of me) as needed to follow the path of keys.

        NeoJSONObject new atPath: #(one two three) put: 42; yourself.
        NeoJSONObject new atPath: #(one two three) put: 42; atPath: #(one two three).
===

HTH,

Sven


Reply | Threaded
Open this post in threaded view
|

Re: How to query a JSON

Sven Van Caekenberghe-2
In reply to this post by Sven Van Caekenberghe-2

> On 24 May 2017, at 17:09, Marc Hanisch <[hidden email]> wrote:
>
> Hello Sven,
>
> Thanks for that hint! It looks like exactly what I need ☺️

Here is a quick example using the new JSON Feed format (https://jsonfeed.org).

json := ZnClient new
  systemPolicy;
  url: 'https://daringfireball.net/feeds/json'; 
  accept: ZnMimeType applicationJson;
  contentReader: [ :entity | NeoJSONObject fromString: entity contents ];
  get.

json items collect: #title.
json items collect: [ :each | each title -> each url ].

Note how you can just pretend that the objects understand #items, #title or #url.

> Best regards,
> Marc
>
> Am 24.05.2017 16:38 schrieb "Sven Van Caekenberghe" <[hidden email]>:
> Marc,
>
> > On 24 May 2017, at 16:20, Marc Hanisch via Pharo-users <[hidden email]> wrote:
>
> > Hello,
> >
> > is there a way to query a JSON with a path (JSONPath or some custom format)?
> >
> > I want to query an API and collect the JSON responses, which I need to iterate over to extract some data. Modelling the JSON structure as classes would be too much overhead, I think. I just want to collect some values...
> >
> > Thanks in advance,
> > Marc
>
> Normally, when you use the NeoJSON package and you don't do any mapping, you get Dictionaries and Arrays back.
>
> There is however also something called NeoJSONObject, a Dictionary subclass that has some API that is quite fluent and that does include path style access.
>
> To get started, use NeoJSONObject class>>#fromString: as parser.
>
> Here is the class comment:
>
> ===
> I am NeoJSONObject.
> I am a Dictionary.
>
> I behave more like a JavaScript object. I return nil for missing keys. I allow any property to be read or set by using a normal accessor message.
>
> The following are equivalent:
>
>         self foo.
>         self at: #foo.
>
> As are the following
>
>         self foo: 1.
>         self at: #foo put: 1.
>
> Except that in the first case, self is returned.
>
> I can optionally be used by NeoJSONReader as mapClass (see #mapClass:).
>
> For output, I act just like my superclass (it is thus not necessary to do any conversions).
>
> Example:
>
>         NeoJSONObject fromString: '{"foo":1,"bar":-2}'.
>         NeoJSONObject new foo: 1; bar: -2.
>         { #x -> 100. #y -> 200 } as: NeoJSONObject.
>         (NeoJSONObject new data: (NeoJSONObject new id: #sensor1; value: 37.5)) asString.
>
> I use JSON as my printed representation. To convert me to JSON, use #printString or #asString.
>
> Additionally, I support path access for nested instances of me, using #atPath: and #atPath:put:
>
> The first is special because it returns nil as soon as a key is missing. The second is special because it creates extra levels (instances of me) as needed to follow the path of keys.
>
>         NeoJSONObject new atPath: #(one two three) put: 42; yourself.
>         NeoJSONObject new atPath: #(one two three) put: 42; atPath: #(one two three).
> ===
>
> HTH,
>
> Sven
>
>


Reply | Threaded
Open this post in threaded view
|

Re: How to query a JSON

Stephane Ducasse-3
In reply to this post by Pharo Smalltalk Users mailing list
mark 
what you can also do is to generate the classes from the json 
we did that for certain libraries.

Stef

On Wed, May 24, 2017 at 4:20 PM, Marc Hanisch via Pharo-users <[hidden email]> wrote:


---------- Forwarded message ----------
From: Marc Hanisch <[hidden email]>
To: Any question about pharo is welcome <[hidden email]>
Cc: 
Bcc: 
Date: Wed, 24 May 2017 16:20:14 +0200
Subject: How to query a JSON
Hello,

is there a way to query a JSON with a path (JSONPath or some custom format)?

I want to query an API and collect the JSON responses, which I need to iterate over to extract some data. Modelling the JSON structure as classes would be too much overhead, I think. I just want to collect some values...

Thanks in advance,
Marc