How do you display multiple JSON data in swiftUI - ios

i would like to know how to access multiple json dates in swiftui.
my problem was that you should connect json data with each other
here is the first jason file:
{
"place": "Mecca",
"type": "Makkiyah",
"count": 7,
"title": "Al-Fatiha",
"titleAr":"الفاتحة",
"index": "001",
"pages": "1",
"juz": [
{
"index": "01",
"verse": {
"start": "verse_1",
"end": "verse_7"
}
}
]
},
{
"place": "Medina",
"type": "Madaniyah",
"count": 286,
"title": "Al-Baqara",
"titleAr":"البقرة",
"index": "002",
"pages": "2",
"juz": [
{
"index": "01",
"verse": {
"start": "verse_1",
"end": "verse_141"
}
},
{
"index": "02",
"verse": {
"start": "verse_142",
"end": "verse_252"
}
},
{
"index": "03",
"verse": {
"start": "verse_253",
"end": "verse_286"
}
}
]
}
here is the second
{`{
"index": "001",
"name": "al-Fatihah",
"verse": {
"verse_1": "بِسْمِ ٱللَّهِ ٱلرَّحْمَٰنِ ٱلرَّحِيمِ",
"verse_2": "ٱلْحَمْدُ لِلَّهِ رَبِّ ٱلْعَٰلَمِينَ",
"verse_3": "ٱلرَّحْمَٰنِ ٱلرَّحِيمِ",
"verse_4": "مَٰلِكِ يَوْمِ ٱلدِّينِ",
"verse_5": "إِيَّاكَ نَعْبُدُ وَإِيَّاكَ نَسْتَعِينُ",
"verse_6": "ٱهْدِنَا ٱلصِّرَٰطَ ٱلْمُسْتَقِيمَ",
"verse_7": "صِرَٰطَ ٱلَّذِينَ أَنْعَمْتَ عَلَيْهِمْ غَيْرِ ٱلْمَغْضُوبِ عَلَيْهِمْ وَلَا ٱلضَّآلِّينَ"
},
"count": 7,
"juz": [
{
"index": "01",
"verse": {
"start": "verse_1",
"end": "verse_7"
}
}
]
The third
{
"index": "01",
"start": {
"index": "001",
"verse": "verse_1",
"name": "Al-Fatiha"
},
"end": {
"index": "002",
"verse": "verse_141",
"name": "Al-Baqara"
}
},
The Last one with Audio
{
"index": "001",
"verse": {
"verse_1": {
"file": "001.mp3",
"size": 27426,
"unit": "26,78 KB"
},
"verse_2": {
"file": "002.mp3",
"size": 26773,
"unit": "26,15 KB"
},
"verse_3": {
"file": "003.mp3",
"size": 21809,
"unit": "21,3 KB"
},
"verse_4": {
"file": "004.mp3",
"size": 17761,
"unit": "17,34 KB"
},
"verse_5": {
"file": "005.mp3",
"size": 25075,
"unit": "24,49 KB"
},
"verse_6": {
"file": "006.mp3",
"size": 23377,
"unit": "22,83 KB"
},
"verse_7": {
"file": "007.mp3",
"size": 63736,
"unit": "62,24 KB"
}
},
"count": 7
}
I hope you can help me.
the whole thing should end up like a book and audio player.
I tried it alone and only called the first json in foreach, how does the rest of the json file go?
the whole thing should end up like a book and audio player.
I hope for your help.
I Love SwiftUI
thank you in advance

Related

Twilio IVR Speech Recognition

I'm new to developing IVR with twilio studio so I started with the basic template and even that's not working.
This is the log:
LOG
Split Based On...
DETAIL
Input evaluated to 'Sales.' from '{{widgets.gather_input.SpeechResult}}'
Transitioning to 'say_play_1' because 'Sales.' did not match any expression
The split is set to "Equal to" sales which then connects the call to a number. It's obviously recognizing the correct speech input but still not working. Any ideas?
{
"description": "IVR",
"states": [
{
"name": "Trigger",
"type": "trigger",
"transitions": [
{
"event": "incomingMessage"
},
{
"next": "gather_input",
"event": "incomingCall"
},
{
"event": "incomingRequest"
}
],
"properties": {
"offset": {
"x": 250,
"y": 50
}
}
},
{
"name": "gather_input",
"type": "gather-input-on-call",
"transitions": [
{
"next": "split_key_press",
"event": "keypress"
},
{
"next": "split_speech_result",
"event": "speech"
},
{
"event": "timeout"
}
],
"properties": {
"voice": "alice",
"speech_timeout": "auto",
"offset": {
"x": 290,
"y": 250
},
"loop": 1,
"hints": "support,sales",
"finish_on_key": "",
"say": "Hello, how can we direct your call? Press 1 for sales, or say sales. To reach support, press 2 or say support.",
"language": "en",
"stop_gather": false,
"gather_language": "en-US",
"profanity_filter": "false",
"timeout": 5
}
},
{
"name": "split_key_press",
"type": "split-based-on",
"transitions": [
{
"event": "noMatch"
},
{
"next": "connect_call_to_sales",
"event": "match",
"conditions": [
{
"friendly_name": "1",
"arguments": [
"{{widgets.gather_input.Digits}}"
],
"type": "equal_to",
"value": "1"
}
]
},
{
"next": "connect_call_to_support",
"event": "match",
"conditions": [
{
"friendly_name": "2",
"arguments": [
"{{widgets.gather_input.Digits}}"
],
"type": "equal_to",
"value": "2"
}
]
}
],
"properties": {
"input": "{{widgets.gather_input.Digits}}",
"offset": {
"x": 100,
"y": 510
}
}
},
{
"name": "split_speech_result",
"type": "split-based-on",
"transitions": [
{
"next": "say_play_1",
"event": "noMatch"
},
{
"next": "connect_call_to_sales",
"event": "match",
"conditions": [
{
"friendly_name": "sales",
"arguments": [
"{{widgets.gather_input.SpeechResult}}"
],
"type": "equal_to",
"value": "sales"
}
]
},
{
"next": "connect_call_to_support",
"event": "match",
"conditions": [
{
"friendly_name": "support",
"arguments": [
"{{widgets.gather_input.SpeechResult}}"
],
"type": "equal_to",
"value": "support"
}
]
}
],
"properties": {
"input": "{{widgets.gather_input.SpeechResult}}",
"offset": {
"x": 510,
"y": 510
}
}
},
{
"name": "connect_call_to_sales",
"type": "connect-call-to",
"transitions": [
{
"event": "callCompleted"
}
],
"properties": {
"offset": {
"x": 100,
"y": 750
},
"caller_id": "{{contact.channel.address}}",
"noun": "number",
"to": "12222222",
"timeout": 30
}
},
{
"name": "connect_call_to_support",
"type": "connect-call-to",
"transitions": [
{
"event": "callCompleted"
}
],
"properties": {
"offset": {
"x": 520,
"y": 750
},
"caller_id": "{{contact.channel.address}}",
"noun": "number",
"to": "12222222",
"timeout": 30
}
},
{
"name": "say_play_1",
"type": "say-play",
"transitions": [
{
"next": "gather_input",
"event": "audioComplete"
}
],
"properties": {
"offset": {
"x": 710,
"y": 200
},
"loop": 1,
"say": "not valid choice."
}
}
],
"initial_state": "Trigger",
"flags": {
"allow_concurrent_calls": true
}
}
Twilio developer evangelist here.
That is weird behaviour, mainly because the log says "evaluated to 'Sales.'". Split widgets conditions are not case-sensitive and should trim leading and following white-space. For some reason this appears to have a capital "S" and a full-stop.
I would suggest a couple of things. Firstly, raise a ticket with Twilio support to look into why the condition didn't match correctly.
Then, try some of the other conditions. When I generate a new IVR template in Studio, the conditions use "Matches any of" instead of "Equal to". You might also try "Contains".
So, experiment with the ways you can match the operators, but get support involved to drill down into why it didn't work in the first place.
The period is needed after the word for some reason...I just put both, for example:
"1, 1., Uno, Uno., Una, Una., Uno, Uno., Español, Español., Español, Español., Español, Español."

Pull Request Lists and the set of approvers from BITBUCKET SERVER API

Is it possible to get the List of all pull request with the details like the date when it was raised, the Person who raised it and the list of all the approvers from the BITBUCKET SERVER using the REST APIs
Absolutely, You can fetch the list of Pull requests along with all the other details like who raised it, when it was raised and who are the reviewers using the following API,
https://docs.atlassian.com/bitbucket-server/rest/7.4.0/bitbucket-rest.html#idp285
You will have the following as response,
{
"size": 1,
"limit": 25,
"isLastPage": true,
"values": [
{
"id": 101,
"version": 1,
"title": "Talking Nerdy",
"description": "It’s a kludge, but put the tuple from the database in the cache.",
"state": "OPEN",
"open": true,
"closed": false,
"createdDate": 1359075920,
"updatedDate": 1359085920,
"fromRef": {
"id": "refs/heads/feature-ABC-123",
"repository": {
"slug": "my-repo",
"name": null,
"project": {
"key": "PRJ"
}
}
},
"toRef": {
"id": "refs/heads/master",
"repository": {
"slug": "my-repo",
"name": null,
"project": {
"key": "PRJ"
}
}
},
"locked": false,
"author": {
"user": {
"name": "tom",
"emailAddress": "tom#example.com",
"id": 115026,
"displayName": "Tom",
"active": true,
"slug": "tom",
"type": "NORMAL"
},
"role": "AUTHOR",
"approved": true,
"status": "APPROVED"
},
"reviewers": [
{
"user": {
"name": "jcitizen",
"emailAddress": "jane#example.com",
"id": 101,
"displayName": "Jane Citizen",
"active": true,
"slug": "jcitizen",
"type": "NORMAL"
},
"lastReviewedCommit": "7549846524f8aed2bd1c0249993ae1bf9d3c9998",
"role": "REVIEWER",
"approved": true,
"status": "APPROVED"
}
],
"participants": [
{
"user": {
"name": "dick",
"emailAddress": "dick#example.com",
"id": 3083181,
"displayName": "Dick",
"active": true,
"slug": "dick",
"type": "NORMAL"
},
"role": "PARTICIPANT",
"approved": false,
"status": "UNAPPROVED"
},
{
"user": {
"name": "harry",
"emailAddress": "harry#example.com",
"id": 99049120,
"displayName": "Harry",
"active": true,
"slug": "harry",
"type": "NORMAL"
},
"role": "PARTICIPANT",
"approved": true,
"status": "APPROVED"
}
],
"links": {
"self": [
{
"href": "http://link/to/pullrequest"
}
]
}
}
],
"start": 0 }

How do I remove optional text from UILabel

I'm trying to remove the Optional text on my UILabel when I run the app. However, I already tried many ways and the Optional persists.
It's important to say that I got these values from JSON, so I created a Struct to decode all this Data. The property ibu is the only one that has Optional written, but if I remove the ? I got an error on JSONDecoder that say's:
Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: "Index
23", intValue: 23), CodingKeys(stringValue: "ibu", intValue: nil)],
debugDescription: "Expected Double value but found null instead.",
underlyingError: nil))
How do I fix that?
App Picture:
Model Folder:
struct Cerveja:Decodable{
let name:String
let image_url:String
let description:String
let tagline:String
let abv:Double
let ibu:Double? //This one that I got the "Optional" written in the UILabel
//If I remove the "?" I got the error below
}
View Folder - Details Screen:
var item:Cerveja?
override func viewDidLoad() {
super.viewDidLoad()
labelName.text = item?.name
labelDescricao.text = item?.description
labelAmargor.text = "\(String(describing: item!.ibu))"
labelTeorAlc.text = "\(item!.abv)"
let resource = ImageResource(downloadURL: URL(string: "\(item?.image_url ?? "")")!, cacheKey: item?.image_url)
imageDetail.kf.setImage(with: resource)
}
Networking Folder:
func getApiData(completion: #escaping ([Cerveja]) -> ()){
guard let urlString = URL(string: "https://api.punkapi.com/v2/beers") else {
print("URL Error")
return
}
Alamofire.request(urlString).responseJSON { response in
if response.data == response.data{
do{
let decoder = try JSONDecoder().decode([Cerveja].self, from: response.data!)
completion(decoder)
}catch{
print(error)
}
}else{print("API Response is Empty")}
}
}
JSON:
[
{
"id": 1,
"name": "Buzz",
"tagline": "A Real Bitter Experience.",
"first_brewed": "09\/2007",
"description": "A light, crisp and bitter IPA brewed with English and American hops. A small batch brewed only once.",
"image_url": "https:\/\/images.punkapi.com\/v2\/keg.png",
"abv": 4.5,
"ibu": 60,
"target_fg": 1010,
"target_og": 1044,
"ebc": 20,
"srm": 10,
"ph": 4.4,
"attenuation_level": 75,
"volume": {
"value": 20,
"unit": "liters"
},
"boil_volume": {
"value": 25,
"unit": "liters"
},
"method": {
"mash_temp": [
{
"temp": {
"value": 64,
"unit": "celsius"
},
"duration": 75
}
],
"fermentation": {
"temp": {
"value": 19,
"unit": "celsius"
}
},
"twist": null
},
"ingredients": {
"malt": [
{
"name": "Maris Otter Extra Pale",
"amount": {
"value": 3.3,
"unit": "kilograms"
}
},
{
"name": "Caramalt",
"amount": {
"value": 0.2,
"unit": "kilograms"
}
},
{
"name": "Munich",
"amount": {
"value": 0.4,
"unit": "kilograms"
}
}
],
"hops": [
{
"name": "Fuggles",
"amount": {
"value": 25,
"unit": "grams"
},
"add": "start",
"attribute": "bitter"
},
{
"name": "First Gold",
"amount": {
"value": 25,
"unit": "grams"
},
"add": "start",
"attribute": "bitter"
},
{
"name": "Fuggles",
"amount": {
"value": 37.5,
"unit": "grams"
},
"add": "middle",
"attribute": "flavour"
},
{
"name": "First Gold",
"amount": {
"value": 37.5,
"unit": "grams"
},
"add": "middle",
"attribute": "flavour"
},
{
"name": "Cascade",
"amount": {
"value": 37.5,
"unit": "grams"
},
"add": "end",
"attribute": "flavour"
}
],
"yeast": "Wyeast 1056 - American Ale\u2122"
},
"food_pairing": [
"Spicy chicken tikka masala",
"Grilled chicken quesadilla",
"Caramel toffee cake"
],
"brewers_tips": "The earthy and floral aromas from the hops can be overpowering. Drop a little Cascade in at the end of the boil to lift the profile with a bit of citrus.",
"contributed_by": "Sam Mason <samjbmason>"
},
{
"id": 2,
"name": "Trashy Blonde",
"tagline": "You Know You Shouldn't",
"first_brewed": "04\/2008",
"description": "A titillating, neurotic, peroxide punk of a Pale Ale. Combining attitude, style, substance, and a little bit of low self esteem for good measure; what would your mother say? The seductive lure of the sassy passion fruit hop proves too much to resist. All that is even before we get onto the fact that there are no additives, preservatives, pasteurization or strings attached. All wrapped up with the customary BrewDog bite and imaginative twist.",
"image_url": "https:\/\/images.punkapi.com\/v2\/2.png",
"abv": 4.1,
"ibu": 41.5,
"target_fg": 1010,
"target_og": 1041.7,
"ebc": 15,
"srm": 15,
"ph": 4.4,
"attenuation_level": 76,
"volume": {
"value": 20,
"unit": "liters"
},
"boil_volume": {
"value": 25,
"unit": "liters"
},
"method": {
"mash_temp": [
{
"temp": {
"value": 69,
"unit": "celsius"
},
"duration": null
}
],
"fermentation": {
"temp": {
"value": 18,
"unit": "celsius"
}
},
"twist": null
},
"ingredients": {
"malt": [
{
"name": "Maris Otter Extra Pale",
"amount": {
"value": 3.25,
"unit": "kilograms"
}
},
{
"name": "Caramalt",
"amount": {
"value": 0.2,
"unit": "kilograms"
}
},
{
"name": "Munich",
"amount": {
"value": 0.4,
"unit": "kilograms"
}
}
],
"hops": [
{
"name": "Amarillo",
"amount": {
"value": 13.8,
"unit": "grams"
},
"add": "start",
"attribute": "bitter"
},
{
"name": "Simcoe",
"amount": {
"value": 13.8,
"unit": "grams"
},
"add": "start",
"attribute": "bitter"
},
{
"name": "Amarillo",
"amount": {
"value": 26.3,
"unit": "grams"
},
"add": "end",
"attribute": "flavour"
},
{
"name": "Motueka",
"amount": {
"value": 18.8,
"unit": "grams"
},
"add": "end",
"attribute": "flavour"
}
],
"yeast": "Wyeast 1056 - American Ale\u2122"
},
"food_pairing": [
"Fresh crab with lemon",
"Garlic butter dipping sauce",
"Goats cheese salad",
"Creamy lemon bar doused in powdered sugar"
],
"brewers_tips": "Be careful not to collect too much wort from the mash. Once the sugars are all washed out there are some very unpleasant grainy tasting compounds that can be extracted into the wort.",
"contributed_by": "Sam Mason <samjbmason>"
},
{
"id": 3,
"name": "Berliner Weisse With Yuzu - B-Sides",
"tagline": "Japanese Citrus Berliner Weisse.",
"first_brewed": "11\/2015",
"description": "Japanese citrus fruit intensifies the sour nature of this German classic.",
"image_url": "https:\/\/images.punkapi.com\/v2\/keg.png",
"abv": 4.2,
"ibu": 8,
"target_fg": 1007,
"target_og": 1040,
"ebc": 8,
"srm": 4,
"ph": 3.2,
"attenuation_level": 83,
"volume": {
"value": 20,
"unit": "liters"
},
"boil_volume": {
"value": 25,
"unit": "liters"
},
"method": {
"mash_temp": [
{
"temp": {
"value": 60,
"unit": "celsius"
},
"duration": 10
},
{
"temp": {
"value": 65,
"unit": "celsius"
},
"duration": 30
},
{
"temp": {
"value": 72,
"unit": "celsius"
},
"duration": 10
},
{
"temp": {
"value": 78,
"unit": "celsius"
},
"duration": 5
}
],
"fermentation": {
"temp": {
"value": 21,
"unit": "celsius"
}
},
"twist": "Soured naturally using the kettle souring technique, Yuzu fruit: 50g at middle, Yuzu juice: 200ml at FV"
},
"ingredients": {
"malt": [
{
"name": "Propino Pale Malt",
"amount": {
"value": 1.63,
"unit": "kilograms"
}
},
{
"name": "Wheat Malt",
"amount": {
"value": 1.63,
"unit": "kilograms"
}
},
{
"name": "Propino Pale Malt for kettle 0.03kg souring",
"amount": {
"value": 0.03,
"unit": "kilograms"
}
},
{
"name": "Acidulated Malt for kettle souring",
"amount": {
"value": 0.03,
"unit": "kilograms"
}
}
],
"hops": [
{
"name": "Bramling Cross",
"amount": {
"value": 10,
"unit": "grams"
},
"add": "middle",
"attribute": "bitter"
}
],
"yeast": "Wyeast 1056 - American Ale\u2122"
}
Use optional binding to avoid this problem
Use
if let ibu = item?.ibu {
labelAmargor.text = "\(String(describing: ibu))"
}
Instead of
labelAmargor.text = "\(String(describing: item!.ibu))"
I would recommend Nil-Coalescing Operator ( ?? ). You can find detailed info here
class Test {
var ibu: Double?
}
var tt: Test? = Test()
tt?.ibu = 3.14
print(String(describing: tt?.ibu)) // Optional("3.14")
print(tt?.ibu ?? 0) // 3.14
tt?.ibu = nil
print(String(describing: tt?.ibu)) // nil
print(tt?.ibu ?? 0) // 0

Geojson gets distorted when trying to render in vega

I try to render a geojson in vega.
I found this example which work fine:
How to read geojson with vega
however, when trying to replace the geojson with one of mine, the features get completely distorted.
{"$schema": "https://vega.github.io/schema/vega/v3.0.json",
"width": 500,
"height": 600,
"autosize": "none",
"signals": [
{
"name": "translate0",
"update": "width / 2"
},
{
"name": "translate1",
"update": "height / 2"
}
],
"projections": [
{
"name": "projection",
"type": "mercator",
"scale": 1000,
"rotate": [
0,
0,
0
],
"center": [
17,
-3
],
"translate": [
{
"signal": "translate0"
},
{
"signal": "translate1"
}
]
}
],
"data": [
{
"name": "drc",
"url": "https://gist.githubusercontent.com/thomas-maschler/ef9891ef03ed4cf3fb23a4378dab485e/raw/47f3632d2135b9a783eeb76d0091762b70677c0d/drc.geojson",
"format": {
"type": "json",
"property": "features"
}
}
],
"marks": [
{
"type": "shape",
"from": {
"data": "drc"
},
"encode": {
"update": {
"strokeWidth": {
"value": 0.5
},
"stroke": {
"value": "darkblue"
},
"fill": {
"value": "lightblue"
},
"fillOpacity": {
"value": 0.5
}
},
"hover": {
"fill": {
"value": "#66C2A5"
},
"strokeWidth": {
"value": 2
},
"stroke": {
"value": "#FC8D62"
}
}
},
"transform": [
{
"type": "geoshape",
"projection": "projection"
}
]
}
]
}
Here is what they are suppose to look like
https://gist.github.com/thomas-maschler/ef9891ef03ed4cf3fb23a4378dab485e
What am I getting wrong?
Thanks,
Thomas
Not sure what happened. It seems your geojson was corrupt, but not really as I eventually could parse it in www.mapshaper.org. I reduced the file to 35% and then it parsed normally:
Vega-lite spec below (compile to Vega code in the editor if needed):
{
"$schema": "https://vega.github.io/schema/vega-lite/v2.json",
"width": 700,
"height": 500,
"config": {"view": {"stroke": "transparent"}},
"layer": [
{
"data": {
"url": "https://gist.githubusercontent.com/mattijn/2ce897c2020a6e5b7ae6baf03dffe179/raw/564b6d484657864dcb77d0bb18db00fc7dc7668d/drc.geojson",
"format": {"type": "json", "property": "features"}
},
"mark": {"type": "geoshape", "stroke": "white", "strokeWidth": 1},
"encoding": {"color": {"value": "#bcbcbc"}}
}
]
}

How to read geojson with vega

It sounds super simple, but I can't get how can I use geojson, not topojson, for my polygons.
that's my current attempt:
"data": [
{
"name": "nabs",
"url": "both_boundaries.geojson",
"format": {"type": "json"},
"transform": [
{
"type": "geopath", "projection": "mercator",
"scale": 74, "center": [-73.99,40.72]
}
]
}
]
You have to parse the features using property within your format:
"format": {"type": "json", "property":"features"},
Full example spec:
{"$schema": "https://vega.github.io/schema/vega/v3.0.json",
"width": 500,
"height": 600,
"autosize": "none",
"signals": [
{
"name": "translate0",
"update": "width / 2"
},
{
"name": "translate1",
"update": "height / 2"
}
],
"projections": [
{
"name": "projection",
"size": {"signal": "[width, height]"},
"fit": {"signal": "data('netherlands')"}
}
],
"data": [
{
"name": "netherlands",
"url": "https://raw.githubusercontent.com/mattijn/datasets/master/NL_outline_geo.json",
"format": {
"type": "json",
"property": "features"
}
}
],
"marks": [
{
"type": "shape",
"from": {
"data": "netherlands"
},
"encode": {
"update": {
"strokeWidth": {
"value": 0.5
},
"stroke": {
"value": "darkblue"
},
"fill": {
"value": "lightblue"
},
"fillOpacity": {
"value": 0.5
}
},
"hover": {
"fill": {
"value": "#66C2A5"
},
"strokeWidth": {
"value": 2
},
"stroke": {
"value": "#FC8D62"
}
}
},
"transform": [
{
"type": "geoshape",
"projection": "projection"
}
]
}
]
}

Resources