Saving an existing JSON file in Firebase using Swift? - json

I have a JSON file, saved locally in my project. Now I'm curious about saving it in Firebase. I know that Firebase saves data in a NoSQL format (as a JSON). I've seen several tutorials about adding files to Firebase, (after some action, like tapping a button in an example iOS app). But is it possible to save a whole JSON file itself (not just chunks of it) in firebase, initially (not after tapping some button), and then load that file, because in my project users can't add files on their own? The app should load the data from JSON file.
I'm new to Firebase, so I have almost no experience using it. If you have any suggestions or know how to do this, I would appreciate your help.
EDITED
Well, to clarify what I am asking about. I have a project which contains a text file, which contains a JSON data. I added it to my project, initially, because I had no experience using Firebase, AWS etc. I just needed to see how the app reacts to data. In the future the data will grow significantly, so obviously I'm not going to save it inside of the project.
The problem is, I just want to save the JSON data in Firebase. And I don't know the right way to do that: by just importing the JSON or writing it from scratch (programmatically or in a console). Also, I would like to know whether it is generally a good idea or not, because this is the first time I'm using online databases, and many people say that Firebase is the best database to start from. I'm really new to all these stuff, that's why I'm asking questions like these.
EDITED_2
{
"list": {
"restaurants": [{
"id": "231311234342bn123",
"name": "Grand Royal",
"suggested": true,
"address": {
"longitude": "30.31527",
"latitude": "59.93688",
"formatted": ["Nevskiy prospekt 10, Saint Petersburg",
"Russian Federation"
]
},
"tags": ["fish",
"Italian",
"Friends"
],
"category": "$$$$",
"description": "Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda.",
"shortDescription": "an",
"collectionName": "Relaxing with friends",
"distance": "1324",
"country": "Russian Federation",
"Region": "North-West region",
"city": "Saint Petersburg"
},
{
"id": "123234344t5213",
"name": "N",
"image": "A",
"suggested": true,
"address": {
"longitude": "30.31821",
"latitude": "59.93605",
"formatted": ["Nevskiy prospekt 15, Saint Petersburg",
"Russian Federation"
]
},
"tags": ["fish",
"french",
"family"
],
"category": "$$$$",
"description": "Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda. ",
"shortDescription": "ab",
"collectionName": "Evening with a family",
"distance": "556",
"country": "Russian Federation",
"Region": "North-West region",
"city": "Saint Petersburg"
}]}}
Here is a snippet of my initial JSON data (it isn't completed, for example, at this moment there is only a string for an image). The data is used throughout the whole app (in a table view, separate views etc.). For example, I use it to populate the table view, use it in a mapView and in other UIViewController subclasses. Also, I need an ability to filter it and to search through it. Currently, I'm doing that by decoding the whole JSON and adding it to an array, and then, I filter that array. But I guess, that isn't the best choice when you have a large amount of data with images.
And one more thing, in Core Data it is possible to set batch requests, so it will initially fetch only some amount of data. It works fine with table views, because when you scroll them, Core Data automatically fetches new data to populate cells. Is it possible to do something like that with firebase, or should I read all data at once?
I've also read that Firebase doesn't require to save array-like data, but there are several ways to solve that issue. It is important to me, because I do need some part of the data to be in an array.

Hopefully this will provide some direction, pardon the length.
Right of the bat, there are usually better ways to store data in Firebase than arrays; arrays are not searchable, editable or addable and if you want to change something the entire array will need to be overridden. Please see Arrays Are Evil.
Secondly Denormalizing Data Is Normal in Firebase. What this means is that when data gets too 'deep' it's much more difficult to query for the data you want. Generally flatter is better - depending on what you want to get out of Firebase.
Third item is there are 100 different ways to work with the data in your question, I'll present two; one to demonstrate conceptually how to write the data and the second is probably a better option.
Here's how to write your data in a brute force kind of way
let addressDict = [
"longitude": "30.31527",
"latitude": "59.93688",
"formatted1": "Nevskiy prospekt 10, Saint Petersburg",
"formatted2": "Russian Federation"
]
let tagsDict = [
"fish": true,
"italian": true,
"friends": true
]
let restaurantDict = [
"name": "Grand Royal",
"suggested": true,
"address": addressDict,
"tags": tagsDict,
"category": "$$$$",
"description": "Lorem ipsum dolor si.",
"shortDescription": "an",
"collectionName": "Relaxing with friends",
"distance": "1324",
"country": "Russian Federation",
"Region": "North-West region",
"city": "Saint Petersburg"
] as [String : Any]
let restaurantsRef = self.ref.child("restaurants").childByAutoId()
restaurantsRef.setValue(restaurantDict)
Running this code will result in a JSON structure similar to your structure. Note that the restaurant key (KzEIkF6nxgWH1nA8B2D) was created automatically when the data is written so that's how the restaurant would be referred to in other structures, by its key.
"restaurants" : {
"-KzEIkF6nxgWH1nA8B2D" : {
"Region" : "North-West region",
"address" : {
"formatted1" : "Nevskiy prospekt 10, Saint Petersburg",
"formatted2" : "Russian Federation",
"latitude" : "59.93688",
"longitude" : "30.31527"
},
"category" : "$$$$",
"city" : "Saint Petersburg",
"collectionName" : "Relaxing with friends",
"country" : "Russian Federation",
"description" : "Lorem ipsum dolor si.",
"distance" : "1324",
"name" : "Grand Royal",
"shortDescription" : "an",
"suggested" : true,
"tags" : {
"fish" : true,
"friends" : true,
"italian" : true
}
}
},
To query for all $$$$ restaurants:
//print all restaurants with $$$$
let restRef = self.ref.child("restaurants")
let query = restRef.queryOrdered(byChild: "category").queryEqual(toValue: "$$$$")
query.observeSingleEvent(of: .value) { snapshot in
for child in snapshot.children {
let snap = child as! DataSnapshot
print(snap)
}
}
While we can query for all restaurants that have a category == "$$$$", the address and tags node are too deep (which is not actually accurate, see Deep Query, but we're going with it for this example as the concept is sound).
So a better structure is
"restaurants" : {
"-KzEIkF6nxgWH1nA8B2D" : {
"Region" : "North-West region",
"category" : "$$$$",
"city" : "Saint Petersburg",
"collectionName" : "Relaxing with friends",
"country" : "Russian Federation",
"description" : "Lorem ipsum dolor si.",
"distance" : "1324",
"name" : "Grand Royal",
"shortDescription" : "an",
"suggested" : true,
}
},
"addresses"
"-KzEIkF6nxgWH1nA8B2D"
"formatted1" : "Nevskiy prospekt 10, Saint Petersburg",
"formatted2" : "Russian Federation",
"latitude" : "59.93688",
"longitude" : "30.31527"
"tags"
"-KzEIkF6nxgWH1nA8B2D"
"fish" : true,
"friends" : true,
"italian" : true
and the code to create it:
let restDict = [
"name": "Jay's Eatery",
"category": "$$$$"
]
let addressDict = [
"formatted1": "Anytown"]
let tagsDict = [
"fish": true,
"friends": true,
"italian": true
]
let restRef = self.ref.child("restaurants")
let addressesRef = self.ref.child("addresses")
let tagsRef = self.ref.child("tags")
let thisRestaurantRef = restRef.childByAutoId()
thisRestaurantRef.setValue(restDict, withCompletionBlock: { (error, snapshot) in
if error == nil {
let thisRestaurantKey = snapshot.key
addressesRef.child(thisRestaurantKey).setValue(addressDict)
tagsRef.child(thisRestaurantKey).setValue(tagsDict)
}
})
Now you can easily query for restaurants with tags of fish, latitude starting with 59 or name of Grand Royal using the query from above.
As you can see, when data in stored in Firebase, there no encoding or decoding involved.
Yes, Firebase can batch load data to populate an array to be used as a tableView datasource
Best practice is to create class object that represents data in your code and to the user, and leverage Firebase on the back in to store that data.
class RestaurantClass {
key = "" //"-KzEIkF6nxgWH1nA8B2D"
name = "" //"Grand Royal
etc
func init(withSnapshot: DataSnapshot) {
//populate the class vars from the snapshot
}
Then the query for $$$$ restaurants would be something like this:
let restRef = self.ref.child("restaurants")
let query = restRef.queryOrdered(byChild: "category").queryEqual(toValue: "$$$$")
query.observeSingleEvent(of: .value) { snapshot in
for child in snapshot.children {
let snap = child as! DataSnapshot
let rest = RestaurantClass(withSnap: snap)
self.myTableViewDataSourceArray.append(rest)
}
self.myTableViewDataSourceArray.reloadData()
}
There's a lot more but this should get you going in the right direction.
The takeaway from this answer is to leverage Firebase to store raw data on the backend - it's blisteringly fast, expandable and maintainable given the data is structured properly. Use classes in code that are populated with that back end data to be used as a datasource and present data to the user.
One final note is if you are working with locations, you're going to want a tool to make that easier. Check out GeoFire for more information.
EDIT:
To address a comment for clarification.
You don't exactly create Firebase data structures in code like you would create properties for a class or struct and it's nothing like a empty SQL table with headers. It's more how you tell Firebase how to write that data. So for example:
ref.child("users").child("uid_0").setValue("Leroy")
tells Firebase that within the users node, write a key: value pair of a string: string of uid: Leroy like this:
users
uid_0: "Leroy"
and
let aDict = ["user_name": "Leroy"]
ref.child("users").child("uid_0").setValue(aDict)
will result in telling Firebase that within the users node to write a key: value pair of a string: dictionary of uid: aDict. Note that aDict is a key: value pair itself of string: string (e.g user_name: Leroy)
users
uid_0
user_name: "Leroy"
I like to think of Firebase is a big Dictionary of key: value pairs where keys are always strings (avoid arrays!) and values are of Any type which could be strings, ints, etc or other Dictionaries.

Related

How do you output processed JSON from AWS Glue to DynamoDB?

{
"adult": false,
"backdrop_path": "/example.jpg",
"belongs_to_collection": null,
"budget": 350000,
"genres": [
{
"id": 18,
"name": "Drama"
}
],
"homepage": "",
"id": 123,
"imdb_id": "a3f4w4f4",
"original_language": "en",
"overview": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum",
"popularity": 27.298,
"poster_path": "/example.jpg",
"production_companies": [
{
"id": 60,
"logo_path": "/example.png",
"name": "example 1",
"origin_country": "US"
},
{
"id": 10212,
"logo_path": null,
"name": "example 2",
"origin_country": ""
}
],
"production_countries": [
{
"iso_3166_1": "US",
"name": "United States of America"
}
],
"release_date": "1970-04-10",
"revenue": 1000000,
"runtime": 97,
"spoken_languages": [
{
"iso_639_1": "en",
"name": "English"
}
],
"status": "Released",
"tagline": "Lorem ipsum.",
"title": "Example name",
"video": false,
"vote_average": 8.5,
"vote_count": 5004
}
I am new to AWS Glue. From what I know it creates a zeppelin notebook that flattens json you throw at it using relationalize transform. Then it normally allows writing to RDS/s3 etc.
I didnt find any good information on directly exporting to dynamodb from AWS glue.
Above is one of the json items in a collection I want to store in dynamodb.
The json fields and keys are identical and consistent with the other json items, albeit some have fewer or more subitems.
If the dynamodb table and schema exists, -- you can assume each json key maps to a dynamo column -- I want AWS Glue to insert or update this json information into dynamo.
How do I do that? Can AWS Glue recreate a dynamo schema? I want to automate as much as possible

Find and update multiple Json data in one column using Laravel and Eloquent

How can I search for a particular "checkNo" and get the value, then update it.
Here is my query that I am using to get the data, but it returns empty:
$isUpdate=DB::table('transactions')->whereIn('pdc_data->checkNo', [35343])->get();
[
{
"calD": "--",
"date": "12-02-2019",
"Int": "3500",
"amount": "20166.666666666668",
"finInt": "403.33333333333337",
"checkNo": "35343",
"remarks": "--",
"bankName": "Fugit eius aut voluptatem fugiat delectus soluta.",
"accountNo": "3353", "branchName": "Aut velit qui qui ut."
},
{
"calD": "--",
"date": "12-17-2019",
"Int": "3500",
"amount": "20166.666666666668",
"finInt": "403.33333333333337",
"checkNo": "35344",
"remarks": "--",
"bankName": "Fugit eius aut voluptatem fugiat delectus soluta.",
"accountNo": "3353", "branchName": "Aut velit qui qui ut."
},
{
"calD": "--",
"date": "01-01-2020",
"Int": "3500",
"amount": "20166.666666666668",
"finInt": "403.33333333333337",
"checkNo": "35345",
"remarks": "--",
"bankName": "Fugit eius aut voluptatem fugiat delectus soluta.",
"accountNo": "3353", "branchName": "Aut velit qui qui ut."
}
]
In order to search in a json colum and use multiple parameters you have to use:
->whereJsonContains('pdc_data->checkNo', ["35343"])
This is the equivalent of the whereIn clause
Also in your json column you are having a string value for this field but you are trying to pass an int so you get no results back cause there is no matching in the variables type.
Just a side note, if you want this field to actually hold an integer value, make sure to store it as an integer so you can check it across same type values.
Checking a string against an integer, or treating an integer as a string can lead you to issues.
You need to decode JSON and then match your query.
You should use transactions table column name in whereIn('column name', '45464') clause.
$data = json_decode($pdc_data, true);
for($data as $value){
$isUpdate=DB::table('transactions')->whereIn('Yourcolumn name', $value->checkNo)->get();
}

Insert comments in Jira with Talend

During my searching, I would like advice about how to insert a comment in Jira issue via Talend Open Studio.
Here is my job :
So, I am trying to insert comment via Talend.
I use a tHttpRequest set like that :
uri is my string connection to get Jira account.
As it's a POST method, my header is Content-Type | application/json.
My post parameters are in a JSON file :
{
"fields": {
"project": {
"key": "TRL"
},
"summary": "A",
"description": "B",
"issuetype": {
"name": "Task"
},
"labels": ["Webapp"],
"reporter": {
"name": "x.x"
},
"assignee": {
"name": "x.x"
}
},
"body": "TEST1",
"visibility": {
"type": "role",
"value": "Administrators"
}}
When I launch this job, the following error appears :
As if the file of the response body was NULL, or maybe It's not the good manner to do the insert of the comment.
I clarify that with Insomnia(insomnia), the insertion of the comment works.
I try also the componant tRest but I don't succeed to link this one with tFileInputDelimited or tJIRAOutput.
Before to continue my work, I want to know if I am in the good direction ? Any clues ?
Thanks by advance,
Ale
I'd recommend using the tRest or tRestClient components. You can just send your JSON as "HTTP body" with these components.
On the JIRA side, you can get the necessary information here: https://developer.atlassian.com/jiradev/jira-apis
Assuming you're working with the on-premise JIRA, you'd use something like this:
URL: hostname + /rest/api/2/issue/{issueIdOrKey}/comment
HTTP Body:
{
"body": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque eget venenatis elit. Duis eu justo eget augue iaculis fermentum. Sed semper quam laoreet nisi egestas at posuere augue semper.",
"visibility": {
"type": "role",
"value": "Administrators"
}
}
Don't forget about the Authentication

Reading JSON Data with inconsistent data index extJS

I am currently trying to read data from an endpoint on my Chef Server using the JSON proxy reader in ExtJS in order to display it on a grid.
Usually the JSON response looks something like this:
{
"userId": 1,
"id": 1,
"title": "sunt aut facere repellat provident occaecati excepturi optioreprehenderit",
"body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
}, {
"userId": 1,
"id": 2,
"title": "qui est esse",
"body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla"
}
However, the response I am receiving from the endpoint, specifically, the organizations/(organization-name)/cookbooks endpoint
comes in like this:
{
"my_cookbook_1": {
"url": "company.com",
"versions": [{
"version": "0.1.0",
"url": "company.com"
}]
}
}, {
"my_cookbook_2": {
"url": "company.com",
"versions": [{
"version": "0.2.0",
"url": "company.com"
}]
}
}
With the former response, I can specify the dataIndex attribute on the grid as name and get the respective information.
var optionalCookbooksGrid = Ext.create('Ext.grid.Panel', {
store: optionalCookbooksStore,
width: '100%',
height: 200,
title: 'Optional Cookbooks',
columns: [{
text: 'Role',
width: 100,
sortable: false,
hideable: false,
dataIndex: 'userID'
}]
});
Because my response from the Chef Server does not have a consistent dataIndex.
How would I display the content to my grid?
I know nothing of extJS so this isn't really a direct answer, but then again this isn't really a Chef question either. Basically the Chef REST API is not built for direct consumption by simple clients. Notably the list endpoint you showed there only gives the name (and URL but that's pretty useless) for each cookbook. From there you need to do N more queries to grab the list of versions for each and then possibly N*M to grab the details for each version. You would normally do this all before feeding the resulting massive data blob in to a UI framework.

Fiware POI add_poi web service fw_media structure

I created json for adding new poi with fw_media data included, based on json from example_components/fw_media.json:
{"fw_core":
{"location":{"wgs84":{"latitude":1,"longitude":1}},
"categories":["Field"],
"name":{"":"poljana 1"}},
"fw_media": {
"entities": [
{
"type": "photo",
"short_label": {
"en": "Sunset at sea"
},
"caption": {
"en": "Sunset on the Bothnian Bay, Northwest from Hailuoto summer 2013"
},
"description": {
"": "Lorem ipsum dolor sit amet, consectetur adipisci elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquid ex ea commodi consequat.",
"fi": "Oli mukava retki."
},
"thumbnail": "http://www.example.org/sunset_on_sea_tbn.jpg",
"url": "http://www.example.org/sunset_on_sea.jpg",
"copyright": "Photo: Ari Okkonen"
},
{
"type": "audio",
"short_label": {
"": "Säkkijärven polkka"
},
"url": "http://www.example.org/sakkijarven_polkka.mp3"
}
],
"last_update": {
"timestamp": 1390203898
}, "source": {
"website": "http://www.cie.fi",
"name": "CIE, University of Oulu",
"id": "7c32c67d-cf00-4d11-9acc-2471141e03a3",
"license": "http://www.gnu.org/licenses/gpl.html"
}
}}
But im getting error:
JSON does not validate. Violations:
[fw_media] The property - source - is not defined and the definition
does not allow additional properties
POI data validation failed!
Can you give me example of working fw_media json?
And also is it possible to upload image with poi in fw_media?(Not just url to image but whole image)
Corrected in master branch in GitHub.
Thank you for your report.
It seems that an old example somewhere has the fw_image.source field that is not implemented. Just edit the source structure out of the data, and it should be Ok. Of course there is no sense to have one source description common for all images, etc. for the one POI.
A source field might be usable in per-item basis. So I'll introduce it to the next release.
Please, could you tell me where that erroneous Sunset at sea is, so I can go correct it. Correction is tracked in https://github.com/Chiru/FIWARE-POIDataProvider/issues/7
I feel uploading pictures a kind of Specific Enabler stuff. So it left to the community to implement. I suggest using some media repository in combination of a standard POI-DP by a specialized client software.