I am trying to extract some data that is being returned in a nested hash from Mailchimp. Here is a trimmed down version of the results I am getting. For each email there are multiple GROUPINGS and for each GROUPING there are multiple GROUPS.
My objective is to get this into a mysql table with a layout like: email_addr, list, grouping1_id, grouping1_name, group1_name, group1_interest, group2_name, group2_interest, grouping2_id, grouping2_name, etc. So there is one row per subscriber with all the grouping and group information.
{"email"=>"dummy#gmail.com", "merges"=>{"EMAIL"=>"dummy#gmail.com",
"GROUPINGS"=>[{"id"=>1, "name"=>"Grouping One", "groups"=>[{"name"=>"Group One",
"interested"=>false}, {"name"=>"Group", "interested"=>true},
{"name"=>"Group Three", "interested"=>true}]}, {"id"=>2, "name"=>"Grouping Two",
"groups"=>[{"name"=>"Group Four", "interested"=>false},
{"name"=>"Group Five", "interested"=>false}]}]}}
Right now, the code I have below runs and inserts the results of the nested blocks into the table but there is one row for each pass through the groups.each_with_index statement. My approach so far seems overly complicated but I am not sure of how to approach this to process the data correctly.
Any help is appreciated.
UPDATED:
I cleaned up the logic a bit and separated the database writes into each level of the hash processing. Now the data is inserted and updated in the database correctly. Although this still feels very inelegant.
def organize_members_subs
#members_data = #members_subs["data"]
#members_data.each do |member|
#email_addr = member["email"]
#db.query("INSERT INTO db.details
(email_addr, list)
VALUES ('#{#email_addr}', '#{#list}' ) ")
groupings = member["merges"]["GROUPINGS"]
groupings.each_with_index do |grouping, index|
#groupings_name = grouping["name"]
#groupings_id = grouping["id"]
#groupings_label = "grp#{index}_"
#db.query("UPDATE db.details
SET grouping#{index}_id = '#{#groupings_id}'
, grouping#{index}_name = '#{#groupings_name}'
WHERE email_addr = '#{#email_addr}' ")
groups = member["merges"]["GROUPINGS"][index]["groups"]
groups.each_with_index do |group, index|
#group_name = group["name"]
#group_interested = group["interested"]
#db.query("UPDATE db.details
SET #{#groupings_label}group#{index}_name = '#{#group_name}'
, #{#groupings_label}group#{index}_int = '#{#group_interested}'
WHERE email_addr = '#{#email_addr}' ")
break if index == groups.length
end
break if index == groupings.length
end
end
end
To start, I wanted to take a closer at look your hash. Rather than reformatting it myself, I did this:
require "awesome_print"
h = `{"email"=>..., "interested"=>false}]}]}}`
ap h
Scroll down to the bottom of my answer to see ap's formatting of the hash.
I will answer your question assuming the db structure is a given, but would like to make a few points:
If "id" is unique for each grouping record, could you make that the key, and dispense with index?
If "name" is unique for each grouping record, could you dispense with both "id" and index?
If "name" is unique for each group record (for a given grouping), could you just have group["name"] => group["interested"] for each group?
Moving on to your code, I will also assume the structure of your hash is given. Later, I will revisit that assumption.
The changes I propose to your code are fairly minor and some are purely stylistic:
Make all instance variables local variables, meaning that two additional arguments must be passed to def organize_members_subs.
With two possible exceptions, eliminate local variables that are only used once after being defined. For example, rather than
groupings_id = grouping["id"], then SET grouping#{index}_id = '#{#groupings_id}', just have SET grouping#{index}_id = '#{grouping["id"]}'.
The two possible exceptions are groupings and groups. For example, you could get rid of the former by writing
member["merges"]["GROUPINGS"].each_with_index do |grouping, index_1|. I'd keep them as variables (so I could easily check their values),
but that's a stylistic decision.
The variable index in groupings.each_with_index do |grouping, index| is in scope within the inner block, which uses an iterator variable with the same name.
I presume that the latter takes precedence, but they should be named differently. I've changed them to index_out and index_in, respectively.
index_out ranges from 0 to groupings.length-1, so break if index_out == groupings.length will never be executed, and therefore may be removed. Ditto for break if index_in == groups.length.
I moved groupings_label = "grp#{index}_" down to draw attention to the fact that it is needed only later, not in the preceding SET expression.
These changes result in the following:
def organize_members_subs(db, list, #members_subs["data"])
members_data.each do |member|
email_addr = member["email"]
db.query("INSERT INTO db.details
(email_addr, list)
VALUES ('#{email_addr}', '#{list}' ) ")
groupings = member["merges"]["GROUPINGS"]
groupings.each_with_index do |grouping, index_out|
db.query("UPDATE db.details
SET grouping#{index_out}_id = '#{grouping["id"]}'
, grouping#{index_out}_name = '#{grouping["name"]}'
WHERE email_addr = '#{email_addr}' ")
groupings_label = "grp#{index_out}_"
groups = member["merges"]["GROUPINGS"][index_out]["groups"]
groups.each_with_index do |group, index_in|
db.query("UPDATE db.details
SET #{groupings_label}group#{index_in}_name = '#{group["name"]}'
, #{groupings_label}group#{index_in}_int = '#{group["interested"]}'
WHERE email_addr = '#{email_addr}' ")
end
end
end
end
Looking at your hash, I am wondering if you could simplify it to the following (formatting courtesy of awesome print):
{
"email" => "dummy#gmail.com",
"merges" => {
"EMAIL" => "dummy#gmail.com",
"GROUPINGS" => {
1 => {
"name" => "Grouping One",
"groups" => {
"Group One" => false,
"Group Two" => true,
"Group Three" => true
}
},
2 => {
"name" => "Grouping Two",
"groups" => {
"Group Four" => false,
"Group Five" => false
}
}
}
}
}
or even
{
"email" => "dummy#gmail.com",
"merges" => {
"EMAIL" => "dummy#gmail.com",
"GROUPINGS" => {
"Grouping One" => {
"Group One" => false,
"Group Two" => true,
"Group Three" => true
},
"Grouping Two" => {
"Group Four" => false,
"Group Five" => false
}
}
}
}
These are not so much as suggestions, but just food for thought.
Awesome print applied to your hash:
ap h # =>
{
"email" => "dummy#gmail.com",
"merges" => {
"EMAIL" => "dummy#gmail.com",
"GROUPINGS" => [
[0] {
"id" => 1,
"name" => "Grouping One",
"groups" => [
[0] {
"name" => "Group One",
"interested" => false
},
[1] {
"name" => "Group",
"interested" => true
},
[2] {
"name" => "Group Three",
"interested" => true
}
]
},
[1] {
"id" => 2,
"name" => "Grouping Two",
"groups" => [
[0] {
"name" => "Group Four",
"interested" => false
},
[1] {
"name" => "Group Five",
"interested" => false
}
]
}
]
}
}
First, maybe extra, but I like to work with symbols since I do a lot of my work in Rails. So let's steal a method from here: How do I convert a Ruby hash so that all of its keys are symbols?
def recursive_symbolize_keys(h)
case h
when Hash
Hash[
h.map do |k, v|
[ k.respond_to?(:to_sym) ? k.to_sym : k, recursive_symbolize_keys(v) ]
end
]
when Enumerable
h.map { |v| recursive_symbolize_keys(v) }
else
h
end
end
OK, lets build a class to make this easier to manipulate and extend as our needs change:
class MemberSub
attr_accessor :email, :groupings, :data_hash, :list, :data_row, :db_sql
def initialize(data_hash)
#convert all keys to symbols
#data_hash = recursive_symbolize_keys(data_hash)
#email = #data_hash[:email]
#list = 'Members'
#groupings = #data_hash[:merges][:GROUPINGS]
#data_row = data_row
#db_sql = db_insert
end
def data_row
#returns a data row for DB
row_hash = {}
row_hash['email'] = #email
row_hash['list'] = #list
gc = 1
#iterate through groupings
#groupings.each_with_index do |grouping, index|
row_hash["grouping#{index + 1}_id"] = grouping[:id]
row_hash["grouping#{index + 1}_name"] = grouping[:name]
#iterate through the groups
grouping[:groups].each do |group|
row_hash["group#{gc}_name"] = group[:name]
row_hash["group#{gc}_interest"] = group[:interested]
gc += 1
end
end
row_hash
end
def db_insert
"INSERT INTO db.details (#{#data_row.keys}) VALUES (#{#data_row.values})".tr('[]','')
end
end
Now you can do feed it a row using what ever iteration method and make a new object:
row = MemberSub.new({"email"=>"dummy#gmail.com", "list"=>"Members", "merges"=>
{"EMAIL"=>"dummy#gmail.com", "GROUPINGS"=>[{"id"=>1, "name"=>"Grouping One", "groups"=>
[{"name"=>"Group One", "interested"=>false}, {"name"=>"Group Two", "interested"=>true},
{"name"=>"Group Three", "interested"=>true}]}, {"id"=>2, "name"=>"Grouping Two", "groups"=>
[{"name"=>"Group Four", "interested"=>false}, {"name"=>"Group Five", "interested"=>false}]}]}})
and make a query:
db.query(row.db_sql)
db.query(INSERT INTO db.details ("email", "list", "grouping1_id", "grouping1_name",
"group1_name", "group1_interest", "group2_name", "group2_interest", "group3_name",
"group3_interest", "grouping2_id", "grouping2_name", "group4_name", "group4_interest",
"group5_name", "group5_interest") VALUES ("dummy#gmail.com", "Members", 1, "Grouping One",
"Group One", false, "Group Two", true, "Group Three", true, 2, "Grouping Two", "Group Four",
false, "Group Five", false))
The other methods should be self explanatory. You don't have to have them all available as attar_accessor but I just did that for example.
Related
This question already has answers here:
Laravel - Eloquent "Has", "With", "WhereHas" - What do they mean?
(2 answers)
Closed 3 months ago.
Hello guys i need to implement filtering result for Document model. My document model have relation with Customer and i need to filter that results with searching multiple columns in customer relation (name and address). I try with traditional way $document->customerRelation->name, customer.name and isn't working.
So i have HTML table with prited documents and there is also printed customer name and customer address. When i type in text box some keywords like (jon or test) i need to filter that columns.
Document
Customer
Address
Document Type
00213
Jon
Test
Inovice
00214
Thomas
Test
Proforma
00215
Agly
Test
Guaranty
00216
Adams
Test
User manual
Here is code
public function index(Request $request)
{
$documents =
Document::when(
$request->has('document_tip_id'), function ($q) use ($request) {
return $q->where('document_tip_id', $request->query('document_tip_id'));
}) // this working
// Here i need to filter by relation (customer.name or address and other columns)
->when(
$request->has('keywords'), function ($q) use ($request) {
return $q->where('customer.name', '%'.$request->query('customer') . '%');
})
->with('products')
->with('customer')
->orderBy('created_at');
$documents = $documents->paginate(20)->withQueryString();
dd($documents);
return ....
}
Dump
Illuminate\Pagination\LengthAwarePaginator {#408 ▼ // app/Http/Controllers/Order/BuyerController.php:38
#items: Illuminate\Database\Eloquent\Collection {#346 ▼
#items: array:20 [▼
0 => App\Models\Document {#321 ▼
#connection: "mysql"
#table: "dokument"
#primaryKey: "id"
#keyType: "int"
#observables: []
#relations: array:2 [▼
"product" => Illuminate\Database\Eloquent\Collection {#343 ▶}
"customer" => App\Models\Customer {#432 ▼
#connection: "mysql"
#table: "customer"
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
+preventsLazyLoading: false
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#escapeWhenCastingToString: false
#attributes: array:28 [▼
"id" => 975
"code" => "123"
"name" => "Jon Don"
"address" => "Test address"
"created_at" => "2020-11-05 21:55:46"
"updated_at" => "2020-11-05 21:55:46"
"deleted_at" => null
]
Model
// Customer.php
public function customer()
{
return $this->belongsTo(Customer::class, 'subjekat_id');
}
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'customer.name'
in 'where clause'
Problem is sloved using whereReklation
->when(
$request->has('keywords'),
function ($q) use ($request) {
return $q->whereRelation('customer', 'name', 'LIKE', '%'.$request->query('keywords') . '%');
})
This is a followup to this question:
Ruby create JSON from SQL Server
I was able to create nested arrays in JSON. But I'm struggling with looping through records and appending a file with each record. Also how would I add a root element just at the top of the json and not on each record. "aaSequences" needs to be at the top just once... I also need a comma between each record.
here is my code so far
require 'pp'
require 'tiny_tds'
require 'awesome_print'
require 'json'
class Document
def initialize strategy
#document = strategy
#load helper functions
load "helpers_ruby.rb"
#set environment 'dev', 'qa', or 'production'
load "envconfig_ruby.rb"
end
def StartUP
#document.StartUP
end
def getseqrecord
#document.getseqrecord
end
end
class GetSqlaaSequence
def StartUP
##system "clear" ##linux
system "cls" ##Windows
# create connection to db
$connReportingDB = createReportingxxSqlConn($ms_sql_host, $ms_sql_user, $ms_sql_password, $ms_sql_dbname)
##$currentDateTime = DateTime.now
##pp 'def StartUP ran at: '+$currentDateTime.to_s
end
def getseqrecord
# get the aaaaSequences data
#result = $connReportingDB.execute("SELECT
[jsonFile]
,[id]
,[title]
,[authorIds]
,[name]
,[aminoAcids]
,[schemaId]
,[registryId]
,[namingStrategy]
FROM tablename
")
$aaSequences = Array.new
#i = 0
#result.each do |aaSequence|
jsonFile = aaSequence['jsonFile']
id = aaSequence['id']
title = aaSequence['title']
authorIds = aaSequence['authorIds']
name = aaSequence['name']
aminoAcids = aaSequence['aminoAcids']
schemaId = aaSequence['schemaId']
registryId = aaSequence['registryId']
namingStrategy = aaSequence['namingStrategy']
##end
#hash = Hash[
"jsonFile", jsonFile,
"id", id,
"title", title,
"authorIds", authorIds,
"name", name,
"aminoAcids", aminoAcids,
"schemaId", schemaId,
"registryId", registryId,
"namingStrategy", namingStrategy
]
#filename = jsonFile
jsonFileOutput0 = {:"#{title}" => [{:authorIds => ["#{authorIds}"],:aminoAcids => "#{aminoAcids}",:name => "#{name}",:schemaId => "#{schemaId}",:registryId => "#{registryId}",:namingStrategy => "#{namingStrategy}"}]}
jsonFileOutput = JSON.pretty_generate(jsonFileOutput0)
File.open(jsonFile,"a") do |f|
f.write(jsonFileOutput)
####ad the comma between records...Not sure if this is the best way to do it...
# File.open(jsonFile,"a") do |f|
# f.write(',')
# end
end
$aaSequences[#i] = #hash
#i = #i + 1
###createReportingSqlConn.close
end
end
end
Document.new(GetSqlaaSequence.new).StartUP
#get aaSequences and create json files
Document.new(GetSqlaaSequence.new).getseqrecord
here is a sample of the json it creates so far...
{
"aaSequences": [
{
"authorIds": [
"fff_fdfdfdfd"
],
"aminoAcids": "aminoAcids_data",
"name": "fdfdfddf-555_1",
"schemaId": "5555fdfd5",
"registryId": "5fdfdfdf",
"namingStrategy": "NEW_IDS"
}
]
}{
"aaSequences": [
{
"authorIds": [
"fff_fdfdfdfd"
],
"aminoAcids": "aminoAcids_data",
"name": "fdfdfddf-555_2",
"schemaId": "5555fdfd5",
"registryId": "5fdfdfdf",
"namingStrategy": "NEW_IDS"
}
]
}
and here is an example of what I need it to look like
{
"aaSequences": [
{
"authorIds": [
"authorIds_data"
],
"aminoAcids": "aminoAcids_data",
"name": "name_data",
"schemaId": "schemaId_data",
"registryId": "registryId_data",
"namingStrategy": "namingStrategy_data"
},
{
"authorIds": [
"authorIds_data"
],
"aminoAcids": "aminoAcids_data",
"name": "name_data",
"schemaId": "schemaId_data",
"registryId": "registryId_data",
"namingStrategy": "namingStrategy_data"
}
]
}
You can just do the whole thing in SQL using FOR JSON.
Unfortunately, arrays are not possible using this method. There are anumber of hacks, but the easiest one in your situation is to just append to [] using JSON_MODIFY
SELECT
authorIds = JSON_MODIFY('[]', 'append $', a.authorIds),
[aminoAcids],
[name],
[schemaId],
[registryId],
[namingStrategy]
FROM aaSequences a
FOR JSON PATH, ROOT('aaSequences');
db<>fiddle
Using Moose, is it possible to create a builder that builds multiple attributes at once?
I have a project in which the object has several 'sets' of fields - if any member of the set is requested, I want to go ahead and populate them all. My assumption is that if I need the name, I'll also need the birthdate, and since they're in the same table, it's faster to get both in one query.
I'm not sure if my question is clear enough, but hopefully some sample code will make it clear.
What I have:
Package WidgetPerson;
use Moose;
has id => (is => 'ro', isa => 'Int' );
has name => (is => 'ro', lazy => 1, builder => '_build_name');
has birthdate => (is => 'ro', lazy => 1, builder => '_build_birthdate');
has address => (is => 'ro', lazy => 1, builder => '_build_address');
sub _build_name {
my $self = shift;
my ($name) = $dbh->selectrow_array("SELECT name FROM people WHERE id = ?", {}, $self->id);
return $name;
}
sub _build_birthdate {
my $self = shift;
my ($date) = $dbh->selectrow_array("SELECT birthdate FROM people WHERE id = ?", {}, $self->id);
return $date;
}
sub _build_address {
my $self = shift;
my ($date) = $dbh->selectrow_array("SELECT address FROM addresses WHERE person_id = ?", {}, $self->id);
return $date;
}
But what I want is:
has name => (is => 'ro', isa => 'Str', lazy => 1, builder => '_build_stuff');
has birthdate => (is => 'ro', isa => 'Date', lazy => 1, builder => '_build_stuff');
has address => (is => 'ro', isa => 'Address', lazy => 1, builder => '_build_address');
sub _build_stuff {
my $self = shift;
my ($name, $date) = $dbh->selectrow_array("SELECT name, birthdate FROM people WHERE id = ?", {}, $self->id);
$self->name($name);
$self->birthdate($date);
}
sub _build_address {
#same as before
}
What I do in this case, when I don't want to have a separate object as in Ether's answer, is have a lazily built attribute for the intermediate state. So, for example:
has raw_row => (is => 'ro', init_arg => undef, lazy => 1, builder => '_build_raw_row');
has birthdate => (is => 'ro', lazy => 1, builder => '_build_birthdate');
sub _build_raw_row {
$dbh->selectrow_hashref(...);
}
sub _build_birthdate {
my $self = shift;
return $self->raw_row->{birthdate};
}
Repeat the same pattern as birthdate for name, etc.
Reading any of the individual attributes will try to get data from raw_row, whose lazy builder will only run the SQL once. Since your attributes are all readonly, you don't have to worry about updating any object state if one of them changes.
This pattern is useful for things like XML documents, too -- the intermediate state you save can be e.g. a DOM, with individual attributes being lazily built from XPath expressions or what-have-you.
No, an attribute builder can only return one value at a time. You could build both by having each builder set the value of the other attribute before returning, but that gets ugly pretty quickly...
However, if you generally have two pieces of data that go together in some way (e.g. coming from the same DB query as in your case), you can store these values together in one attribute as an object:
has birth_info => (
is => 'ro', isa => 'MyApp::Data::BirthInfo',
lazy => 1,
default => sub {
MyApp::Data::BirthInfo->new(shift->some_id)
},
handles => [ qw(birthdate name) ],
);
package MyApp::Data::BirthInfo;
use Moose;
has some_id => (
is => 'ro', isa => 'Int',
trigger => sub {
# perhaps this object self-populates from the DB when you assign its id?
# or use some other mechanism to load the row in an ORMish way (perhaps BUILD)
}
);
has birthdate => (
is => 'ro', isa => 'Str',
);
has name => (
is => 'ro', isa => 'Str',
);
I'm creating a job in Ruby which takes info from a mysql database and sends it to a html page to create a widget. The thing is, I can't get the data to be displayed when I take it out of a mysql database, however when I type the input in manually and send that to the html page...it works!
require 'Mysql2'
SCHEDULER.every '10s', :first_in => 0 do |job|
$application, $details, $timestamp = 0
table = Array.new
client = Mysql2::Client.new(:host => "localhost", :username => "****", :password => "****", :database => "Sample_Database")
#Gets statistics for latest input
sstc = client.query("SELECT * FROM Probably_Serious_Alerts")
sstc.each do |row|
$row = "{ cols: [ {value: '" + row["time_stamp"].to_s + "'}, {value: '"+ row["application"].to_s + "'}, {value: '" + row["details"].to_s + "'}]}"
table.push($row)
end
rows = "rows = ["
for row in table
rows = rows + row + ","
end
rows = rows[0...-1]
rows = rows + ']'
hrows = [
{ cols: [ {value: 'Time'}, {value: 'Monitoring System'}, {value: 'Event'}]}
]
sleep(1)
#rows = [
# { cols: [ {value: '2016-09-19 14:39:30 +0100'}, {value: 'Solarwinds'}, {value: 'First Solarwinds Error'}]},
# { cols: [ {value: '2016-09-19 15:24:17 +0100'}, {value: 'Nagios'}, {value: 'First Nagios'}]}]
puts rows
send_event('my-table', { hrows: hrows, rows: rows } )
end
The commented code is the code which is printed to the terminal when I run it. This is also what I send to the HTML page and works on the widget. Any ideas? Is something async?
I know it's a bit late but since I stumbled upon this question on Stackoverflow when Googling for the same issue I had when trying to push data to the Smashing Table Widget I thought someone else might be happy if I shared my solution. The issue in your code is that you put the rows object you return as a string, however the Table Widget expects, let me quote from the Documentation:
To send a row to the tbody (or thead), send a array of hashes to rows (hrows for thead). The bindings work from row to column. Every column should be it's own array element off a cols hash. The hash must have a key of "value" in order to show up. To send multiple rows, use an array of these hashes.
So you have to transform the MySQL Result into an Array of Hashes. See my code below, note that "Loc Nr.", "Address" and "Status" are the Column Names of my MySQL Table:
results = db.query(sql)
hrows = [
{ cols: [ {value: 'Loc Nr.'}, {value: 'Address'}, {value: 'Status'}]}
]
table = Array.new
results.each do |row|
table.push({ cols: [ {value: row['Loc Nr.']}, {value: row['Address']}, {value: row['Status']}]})
end
send_event('locations', { hrows: hrows, rows: table } )
Hope you already found the solution but it might help someone else :D
So I'm trying to pull data from a JSON string (as seen below). When I decode the JSON using the code below, and then attempt to index the duration text, I get a nil return. I have tried everything and nothing seems to work.
Here is the Google Distance Matrix API JSON:
{
"destination_addresses" : [ "San Francisco, CA, USA" ],
"origin_addresses" : [ "Seattle, WA, USA" ],
"rows" : [
{
"elements" : [
{
"distance" : {
"text" : "1,299 km",
"value" : 1299026
},
"duration" : {
"text" : "12 hours 18 mins",
"value" : 44303
},
"status" : "OK"
}]
}],
"status" : "OK"
}
And here is my code:
local json = require ("json")
local http = require("socket.http")
local myNewData1 = {}
local SaveData1 = function (event)
distanceReturn = ""
distance = ""
local URL1 = "http://maps.googleapis.com/maps/api/distancematrix/json?origins=Seattle&destinations=San+Francisco&mode=driving&&sensor=false"
local response1 = http.request(URL1)
local data2 = json.decode(response1)
if response1 == nil then
native.showAlert( "Data is nill", { "OK"})
print("Error1")
distanceReturn = "Error1"
elseif data2 == nill then
distanceReturn = "Error2"
native.showAlert( "Data is nill", { "OK"})
print("Error2")
else
for i = 1, #data2 do
print("Working")
print(data2[i].rows)
for j = 1, #data2[i].rows, 1 do
print("\t" .. data2[i].rows[j])
for k = 1, #data2[i].rows[k].elements, 1 do
print("\t" .. data2[i].rows[j].elements[k])
for g = 1, #data2[i].rows[k].elements[k].duration, 1 do
print("\t" .. data2[i].rows[k].elements[k].duration[g])
for f = 1, #data2[i].rows[k].elements[k].duration[g].text, 1 do
print("\t" .. data2[i].rows[k].elements[k].duration[g].text)
distance = data2[i].rows[k].elements[k].duration[g].text
distanceReturn = data2[i].rows[k].elements[k].duration[g].text
end
end
end
end
end
end
timer.performWithDelay (100, SaveData1, 999999)
Your loops are not correct. Try this shorter solution.
Replace all your "for i = 1, #data2 do" loop for this one below:
print("Working")
for i,row in ipairs(data2.rows) do
for j,element in ipairs(row.elements) do
print(element.duration.text)
end
end
This question was solved on Corona Forums by Rob Miracle (http://forums.coronalabs.com/topic/47319-parsing-json-from-google-distance-matrix-api/?hl=print_r#entry244400). The solution is simple:
"JSON and Lua tables are almost identical data structures. In this case your table data2 has top level entries:
data2.destination_addresses
data2.origin_addresses
data2.rows
data2.status
Now data2.rows is another table that is indexed by numbers (the [] brackets) but here is only one of them, but its still an array entry:
data.rows[1]
Then inside of it is another numerically indexed table called elements.
So far to get to the element they are (again there is only one of them
data2.rows[1].elements[1]
then it's just accessing the remaining elements:
data2.rows[1].elements[1].distance.text
data2.rows[1].elements[1].distance.value
data2.rows[1].elements[1].duration.text
data2.rows[1].elements[1].duration.value
There is a great table printing function called print_r which can be found in the community code which is great for dumping tables like this to see their structure."