How to iterate over JSON and parse values?

Post your questions and help other users.

Moderator: Martin

Post Reply
lord_EarlGray
Posts: 19
Joined: 16 Jun 2018 21:17

How to iterate over JSON and parse values?

Post by lord_EarlGray » 26 Jan 2019 22:18

Hi,

I'm working on flow, that will get JSON from news API, find only today's news, and create task bar notification with header of news and link to read full context.
Fetching data from API works fine, but I don't know how to iterate ovet this JSON and get only todays objects.

API response looks like this:

Code: Select all

{
    "status": "ok",
    "feed": {
        "url": "https://epoznan.pl/rss.php",
        "title": "Wiadomości epoznan.pl",
        "link": "http://wiadomosci.epoznan.pl/",
        "author": "",
        "description": "Najświeższe informacje z Poznania",
        "image": "http://epoznan.pl/gallery2/25707/pbpjj7bg8q6j3vthhgjprhf7yvjn7yfv.jpg"
    },
    "items": [
        {
            "title": "Poznań w 1945 i dziś na fotomontażach",
            "pubDate": "2016-02-23 07:03:00",
            "link": "http://epoznan.pl/news-news-64977",
            "guid": "item_story64977",
            "author": "",
            "thumbnail": "",
            "description": "We wtorek przypada 71. rocznica zakończenia niemieckiej okupacji i walk o Poznań. Już w poniedziałek pokazywaliśmy archiwalny film z Cytadeli, która była ostatnim punktem oporu wojsk niemieckich. Dziś prezentujemy niezwykłe fotomontaże, na których współczesny Poznań zestawiono ze zdjęciami z 1945 roku.",
            "content": "We wtorek przypada 71. rocznica zakończenia niemieckiej okupacji i walk o Poznań. Już w poniedziałek pokazywaliśmy archiwalny film z Cytadeli, która była ostatnim punktem oporu wojsk niemieckich. Dziś prezentujemy niezwykłe fotomontaże, na których współczesny Poznań zestawiono ze zdjęciami z 1945 roku.",
            "enclosure": {},
            "categories": []
        },
        {
            "title": "Warta Poznań wygrała sparing z Mieszkiem Gniezno",
            "pubDate": "2019-01-26 15:06:11",
            "link": "http://epoznan.pl/news-news-92084",
            "guid": "item_news92084",
            "author": "",
            "thumbnail": "",
            "description": "Czwarty mecz sparingowy mają za sobą piłkarze Warty Poznań.",
            "content": "Czwarty mecz sparingowy mają za sobą piłkarze Warty Poznań.",
            "enclosure": {},
            "categories": []
        },
        {
            "title": "Nieznana substancja w Cybinie. Strażacy ustawiają zapory",
            "pubDate": "2019-01-26 14:36:17",
            "link": "http://epoznan.pl/news-news-92083",
            "guid": "item_news92083",
            "author": "",
            "thumbnail": "",
            "description": "Strażacy zgłoszenie odebrali około godziny 13.",
            "content": "Strażacy zgłoszenie odebrali około godziny 13.",
            "enclosure": {},
            "categories": []
        },
        {
            "title": "Mężczyzna wszedł do silosu i stracił przytomność. W ciężkim stanie trafił do szpitala",
            "pubDate": "2019-01-26 14:04:24",
            "link": "http://epoznan.pl/news-news-92082",
            "guid": "item_news92082",
            "author": "",
            "thumbnail": "",
            "description": "Do zdarzenia doszło około godziny 12 pod Kaliszem.",
            "content": "Do zdarzenia doszło około godziny 12 pod Kaliszem.",
            "enclosure": {},
            "categories": []
        }
    ]
}
The first of "items" is outdated, and I don't need it. I want to fetch only last 3 "items". I need to compare "pubDate" values somehow. I have variable, that holds current date in format YYYY-MM-DD, but in JSON "pubDate" also contains time. I want to compare only dates and I don't know how to do that. Also I don't know how to store all of the "items" in some sort of structure (list I guess), and than to iterate over it to get data that I need - "title" and "link".

I will appreciate if someone could make sketch of such script.

User avatar
Desmanto
Posts: 2709
Joined: 21 Jul 2017 17:50

Re: How to iterate over JSON and parse values?

Post by Desmanto » 27 Jan 2019 05:48

Use action HTTP request to retrieve the json. I think the url should be "https://epoznan.pl/rss.php". Then save the result in {response}

You have to convert this JSON to an object (nested map/list), using fromJSON(). Then you can iterate over the items inside.

Code: Select all

js = fromJSON(response);
today = getDate("{getDate(),dateformat,yyyy-MM-dd}", "yyyy-MM-dd");

news = newList();
for(i in js["items"])
{
  pubDate = getDate(i["pubDate"], "yyyy-MM-dd");
  if(pubDate == today)
    addElement(news, newList(i["title"], i["link"], i["pubDate"]) );
}
To get today date without any hour minute second, use the getDate() with dateformat and getDate() pattern from it. I believe there is a better way to do this, but currently this is what I use.

We iterate only the items, as that is the element which contains the list of the news. Check the pubDate, you can use getDate(date, patterns). Even though the date is "2016-02-23 07:03:00", if we use pattern "yyyy-MM-dd", it will take only the year month day, not the hour minute second. So this will give us 2016-02-23 00:00:00. Compare this to today's date, if match, then pull the news and add the title, link and the pubDate to the {news} list.

The {news} will be a nested listed, contain all the today news, with the nested list contain : title, link, date (index 0, 1, 2). Use condition debug dialog to check the value. You can also use this as choices, by adding it to a new list.

Code: Select all

choice = newList();
for(i in news)
  addElement(choice, i[0]);
Then use {choice,listformat,comma} in the input dialog - Single Choice Menu, to select one of the news.


The above will compare only the today news. Sometimes there are only few news and you don't read it frequently. So maybe you read it in 3-4 days span range. You can simply just check any news during the last week. You don't need {today} anymore, simply subtract current datetime by 7 days (-7).

Code: Select all

js = fromJSON(response);

news = newList();
for(i in js["items"])
{
  pubDate = getDate(i["pubDate"], "yyyy-MM-dd");
  if(pubDate > addDays(getDate(), -7))
    addElement(news, newList(i["title"], i["link"], i["pubDate"]) );
}
Index of Automagic useful thread List of my other useful posts (and others')
Xiaomi Redmi Note 5 (whyred), AOSP Extended v6.7 build 20200310 Official, Android Pie 9.0, Rooted.

lord_EarlGray
Posts: 19
Joined: 16 Jun 2018 21:17

Re: How to iterate over JSON and parse values?

Post by lord_EarlGray » 29 Jan 2019 18:28

Thanks for your reply. I have tried your last solution:

Code: Select all

js = fromJSON(response);

news = newList();
for(i in js["items"])
{
  pubDate = getDate(i["pubDate"], "yyyy-MM-dd");
  if(pubDate > addDays(getDate(), -7))
    addElement(news, newList(i["title"], i["link"], i["pubDate"]) );
}
and it seems to work fine for me. Not sure if I understand correctly "-7" - will it show me news from today and 7 days before?
Purpose of this script is to fetch news from the current day and the day before. I want to run it each morning after my alarm rings (I think there is some kind of trigger for that), so I can chceck news from my city before going to work (in case of some traffic problems) without opening any external news apps.

The other thing that still concernes me is how to create nice notification on status bar with data from this list. I think, the good template for that should be:
News Title
News Date
News Description
Clicable Link

News Title
News Date
News Description
Clicable Link

...


I think, I should iterate over newList and extract data, but inside "notification on status bar" action. Not sure if this is possible...

User avatar
Desmanto
Posts: 2709
Joined: 21 Jul 2017 17:50

Re: How to iterate over JSON and parse values?

Post by Desmanto » 30 Jan 2019 18:06

Yes, -7 means current datetime minus 7 days, so a week ago. If it is too far, you can use -2, from 2 days ago.

To have it run every morning, you can just use Trigger Time, set it at time pass your alarm time, and before you go to work. But if you need it after the alarm, you can use Trigger Notification on Statusbar Removed, use your alarm notification as the filter.

I think it is too ugly to show all the news title and description in the notification bar. It can be done, but it will clutter and not clean. And the way to do it depends on whether you read all the news or you simply pick one or two of them to read.
It is better to show the news list in the message dialog, or even better, input dialog - single choice menu. I have modified the script, reorder the news element to suit your order

Code: Select all

js = fromJSON(response);

news = newList();
for(i in js["items"])
{
  pubDate = getDate(i["pubDate"], "yyyy-MM-dd");
  if(pubDate > addDays(getDate(), -2))
    addElement(news, newList(i["title"], i["pubDate"], i["description"], i["link"])  );
}

choice = newList();
for(i in news)
  addElement(choice, i[0] + "\n" + i[1] + "\n" + i[2] + "\n");
The addition is the {choice} list, which is the concatenation from the {news} list to single element. You then show the choice list in the input dialog using {choice,listformat, comma}

After the input dialog, put expression

Code: Select all

if(operation == "ok")
{
  url = news[index][3];
  return true;
}
return false;
Anything you choose from the input dialog will be matched back to the news index, retrieve the link and store it in {url}. You can then use Browse URL, use the {url} as the link and open with your favourite browser.


Now, if you only read one of the news only, you can simply use trigger time or notification on statusbar removed for the alarm. But in case you want to read the 2nd news too after reading one of them, you have to execute the flow again. That's where you need the trigger shortcut, the easiest one of all. Simply tap it again and choose other news to open in the browser. But kinda defeat the purpose, since if you have browsed to the page, most likely the other news also already presented in the side bar of the news you are currently reading. It is just one tap away.

But that depends on your need, you probably need it any way, as a quickshortcut to access the latest news maybe.
Index of Automagic useful thread List of my other useful posts (and others')
Xiaomi Redmi Note 5 (whyred), AOSP Extended v6.7 build 20200310 Official, Android Pie 9.0, Rooted.

Post Reply