Json parsing

Hi

I've a json file (surely not the only person :wink:
How can I best access the fields _directly_?
Example: j=[{a: { b: {c: { d: { e: :f}}}}}, {g: [1,2]} , 0]
mykey should allow direct access as if it were a "flattened" hash / array.
- so its not digging throught the dirt, more like a long-range missile shooting direclty on the targets, without collateral damage :slight_smile:

j.mykey(:c) => { d: { e: :f}}}}
j.mykey(:g) => [1,2]
j.mykey(:g,1) => 2
j.mykey(1) => 0

# if ambiguous, then all possible solutions should be shown (and a warning/exception is raised)

# if it makes not too complicated: j.mykey(0,1) => {g: {1,2]} ## second hash inside the first array-element (normally we can't address hashes with the position...

thanks
Opti

Hi

I've a json file (surely not the only person :wink:
How can I best access the fields _directly_?
Example: j=[{a: { b: {c: { d: { e: :f}}}}}, {g: [1,2]} , 0]
mykey should allow direct access as if it were a "flattened" hash / array.
- so its not digging throught the dirt, more like a long-range missile shooting direclty on the targets, without collateral damage :slight_smile:

j.mykey(:c) => { d: { e: :f}}
j.mykey(:g) => [1,2]
j.mykey(:g,1) => 2
j.mykey(1) => 0

# if ambiguous, then all possible solutions should be shown (and a warning/exception is raised)

# if it makes not too complicated: j.mykey(0,1) => {g: {1,2]} ## second hash inside the first array-element (normally we can't address hashes with the position...
Indices can be easily distingued from hash-keys (no numbers allowed)

thanks
Opti

路路路

On 2017-01-16 22:43, Die Optimisten wrote:

I've a json file (surely not the only person :wink:
How can I best access the fields _directly_?
Example: j=[{a: { b: {c: { d: { e: :f}}}}}, {g: [1,2]} , 0]
mykey should allow direct access as if it were a "flattened" hash / array.
- so its not digging throught the dirt, more like a long-range missile
shooting direclty on the targets, without collateral damage :slight_smile:

If the JSON file is complex enough that this is causing you pain, then it might be an idea to create some sort of class to deal with the job of representing the data to the rest of your application.

Inside such a class, arguably constructs such as `j[1][:g][0]` are at the very least forgivable.

Click here to view Company Information and Confidentiality Notice.<http://www.jameshall.co.uk/index.php/small-print/email-disclaimer&gt;

Well, if you assume a GUIDED missile, you can use `dig`

irb2.4.0> j=[{a: { b: {c: { d: { e: :f}}}}}, {g: [1,2]} , 0]
#2.4.0 => [{:a=>{:b=>{:c=>{:d=>{:e=>:f}}}}}, {:g=>[1, 2]}, 0]

irb2.4.0> j.dig(0, :a, :b, :c)
#2.4.0 => {:d=>{:e=>:f}}

irb2.4.0> j.dig(1, :g, 1)
#2.4.0 => 2

-Rob

路路路

On 2017-Jan-16, at 16:47 , Die Optimisten <inform@die-optimisten.net> wrote:

On 2017-01-16 22:43, Die Optimisten wrote:
Hi

I've a json file (surely not the only person :wink:
How can I best access the fields _directly_?
Example: j=[{a: { b: {c: { d: { e: :f}}}}}, {g: [1,2]} , 0]
mykey should allow direct access as if it were a "flattened" hash / array.
- so its not digging throught the dirt, more like a long-range missile shooting direclty on the targets, without collateral damage :slight_smile:

j.mykey(:c) => { d: { e: :f}}
j.mykey(:g) => [1,2]
j.mykey(:g,1) => 2
j.mykey(1) => 0

# if ambiguous, then all possible solutions should be shown (and a warning/exception is raised)

# if it makes not too complicated: j.mykey(0,1) => {g: {1,2]} ## second hash inside the first array-element (normally we can't address hashes with the position...
Indices can be easily distingued from hash-keys (no numbers allowed)

thanks
Opti

Hi

I've a json file (surely not the only person :wink:
How can I best access the fields _directly_?
Example: j=[{a: { b: {c: { d: { e: :f}}}}}, {g: [1,2]} , 0]
mykey should allow direct access as if it were a "flattened" hash / array.
- so its not digging throught the dirt, more like a long-range missile shooting direclty on the targets,
without collateral damage :slight_smile:

j.mykey(:c) => { d: { e: :f}}
j.mykey(:g) => [1,2]
j.mykey(:g,1) => 2
j.mykey(1) => 0

if the '1' should be an index, shouldn't it ne {g: [1,2]}

# if ambiguous, then all possible solutions should be shown (and a warning/exception is raised)

do you want to have some kind of flexible search engine for arbitrary hash-array-whatElse elements?

# if it makes not too complicated: j.mykey(0,1) => {g: {1,2]} ## second hash inside the first array-element
(normally we can't address hashes with the position...
Indices can be easily distingued from hash-keys (no numbers allowed)

your wishes sound all so simple, but if you think of it from a language perspective (keep in mind all
combinations are possible) - they are overwhelming. if you restrict yourself to just hashes and arrays, you
could write your on "find" method, though. Everything above this level sounds (at least to me) like: "Let's
have a simple google search for our database!" (btw, a real sentence from one of my former customers)

cheers
ralf

路路路

On 01/16/2017 10:47 PM, Die Optimisten wrote:

On 2017-01-16 22:43, Die Optimisten wrote:

Hi
My problem is: how to traverse the json file?
I can iterate over keys (or values) but I don't get it for traversing depth...
I would prefer traversing over recursion, but perhaps recursion is easier?
Any ideas how to do that? (build a tree containing all keys and array-items (array-beginning if item its linear, meaning nothing in the level below)

thanks
Opti

路路路

On 2017-01-17 10:01, Andy Jones wrote:

I've a json file (surely not the only person :wink:
How can I best access the fields _directly_?
Example: j=[{a: { b: {c: { d: { e: :f}}}}}, {g: [1,2]} , 0]
mykey should allow direct access as if it were a "flattened" hash / array.
- so its not digging throught the dirt, more like a long-range missile
shooting direclty on the targets, without collateral damage :slight_smile:

If the JSON file is complex enough that this is causing you pain, then it might be an idea to create some sort of class to deal with the job of representing the data to the rest of your application.

Inside such a class, arguably constructs such as `j[1][:g][0]` are at the very least forgivable.

My problem is: how to traverse the json file?
I can iterate over keys (or values) but I don't get it for traversing
depth...

This rather depends how much you can rely on in regard to the JSON file's structure. I'm going to assume that you are not building a generic solution to traverse all possible JSON files?

(BTW goggle "JSON Schema" if you haven't come across the idea -- there are Ruby libraries that will help you validate your JSON, if you can define the structure.)

So if you know, for example, that the top level should be a key :foo which should contain an array, then it seems to me that the simplest way to proceed would be to iterate through the array and build an array of objects of class Foo -- each of which would take their array element as an initialiser.

If your JSON is a deeply nested Hash (for example, for the Foo class above) and you know the structure, you can just `@boz = json_string[:bar][:baz][:boz]`. Or use dig() if you prefer.

I would prefer traversing over recursion, but perhaps recursion is easier?

I would say that if you are looking to traverse an arbitrary data structure depth-wise, recursion is the way to go. But it really depends on the data structure and what you are trying to get out of it -- and how comfortable you are with recursion.

I might also say "don't try to traverse an arbitrary data structure depth-wise if you can possibly help it, that sounds like a hell of a lot of work".

Any ideas how to do that? (build a tree containing all keys and
array-items (array-beginning if item its linear, meaning nothing in the
level below)

You can do that trivially with JSON.parse. I mean, a tree of all keys and data items is what you get when you parse JSON into Ruby, right? The real trick is to make sense of the tree afterwards?

For which, at the end of the day, you will have to know *something* about its structure...

Click here to view Company Information and Confidentiality Notice.<http://www.jameshall.co.uk/index.php/small-print/email-disclaimer&gt;

Hi
as I understand, json consists only of hashes, arrays (and numbers and strings)
So i'm targetting a parser for any json file, which allows to access a specific element (or part) by name, independent of its position.

@boz = mykey[:boz] # directly (autonome missile finding the target itself!)
mykey would be a lookup-list (hash)
the traversal for filling that linear list has to go through the tree
lookupList = Hash(names, values)
  values is an array with all occurences, containing the positions for dig (as subarray)

Looks not so hard...,
BUT seems too hard for beginners like me...

Opti

路路路

On 2017-01-17 13:58, Andy Jones wrote:

My problem is: how to traverse the json file?
I can iterate over keys (or values) but I don't get it for traversing
depth...

This rather depends how much you can rely on in regard to the JSON file's structure. I'm going to assume that you are not building a generic solution to traverse all possible JSON files?

(BTW goggle "JSON Schema" if you haven't come across the idea -- there are Ruby libraries that will help you validate your JSON, if you can define the structure.)

So if you know, for example, that the top level should be a key :foo which should contain an array, then it seems to me that the simplest way to proceed would be to iterate through the array and build an array of objects of class Foo -- each of which would take their array element as an initialiser.

If your JSON is a deeply nested Hash (for example, for the Foo class above) and you know the structure, you can just `@boz = json_string[:bar][:baz][:boz]`. Or use dig() if you prefer.

as I understand, json consists only of hashes, arrays (and numbers and
strings)

...and Booleans...

So i'm targetting a parser for any json file, which allows to access a
specific element (or part) by name, independent of its position.

How do you know that the name is unique? This is perfectly valid JSON:

    { "foo": [ 1, { "foo": { "foo": 4 } ] } }

@boz = mykey[:boz] # directly (autonome missile finding the target
itself!)
mykey would be a lookup-list (hash)
the traversal for filling that linear list has to go through the tree
lookupList = Hash(names, values)
  values is an array with all occurences, containing the positions for
dig (as subarray)

Assuming every key in your entire JSON file *is* unique, then you could just flatten the entire thing into a single flat Hash (good case for recursion here) and then your `mykey[:boz]` above would be plain Ruby.

But that's quite an assumption.

And, really, what is this giving you that dig() does not?

Click here to view Company Information and Confidentiality Notice.<http://www.jameshall.co.uk/index.php/small-print/email-disclaimer&gt;

as I understand, json consists only of hashes, arrays (and numbers and
strings)

...and Booleans...

ok, but they can be handled as strings.

So i'm targeting a parser for any json file, which allows to access a
specific element (or part) by name, independent of its position.

How do you know that the name is unique? This is perfectly valid JSON:

     { "foo": [ 1, { "foo": { "foo": 4 } ] } }

With not uniq names, result (value for each key) would be an array containing the positions.

@boz = mykey[:boz] # directly (autonome missile finding the target
itself!)
mykey would be a lookup-list (hash)
the traversal for filling that linear list has to go through the tree
lookupList = Hash(names, values)
   values is an array with all occurences, containing the positions for
dig (as subarray)

And, really, what is this giving you that dig() does not?

I do not know the structure (and keynames) of the json file!
So a hash pointing to the positions (or the field-contents) is pretty much easier to handle...

Opti

路路路

On 2017-01-17 14:43, Andy Jones wrote: