I've been looking around and learning JSON a little bit. I thought it would be good to start learning with something easy but it seems it is not. I am trying to do JSON database. For example it has brand names and every brand has its own products with some info. I've done that like this which is actually much longer:
{
"Snuses": {
"Brands": {
"CATCH": [
{
"Products": "CATCH EUCALYPTUS WHITE LARGE",
"nicotine": "8.0"
}
]
}
Now I am using Firebase to parse the "Brands" like "CATCH" etc.. But I can't.
In swift I am trying to do it like this:
override func viewDidLoad() {
super.viewDidLoad()
ref = FIRDatabase.database().reference()
ref.observeSingleEventOfType(.Value, withBlock: { snapshot in
self.ref = FIRDatabase.database().reference().child("Snuses").child("Brands")
self.ref.observeEventType(.Value, withBlock: { snapshot -> Void in
for brands in snapshot.children {
print(brands)
}
})
})
}
How to get reference to the Brands first? And how to store list of brands separately?
Some smart guys told me that it is not correct to do but I don't know what is wrong with the JSON structure. How can I flatten it?
I red the docs also that says how it is best to do it but it is a little to complicaetd. Can you point me to the right direction?
You just need to do allKeys to get allKeys from snap
let ref = FIRDatabase.database().reference().child("Snuses").child("Brands")
ref.observeSingleEventOfType(.Value, withBlock: { (snapshot) in
if snapshot.exists() {
if let allProducts = (snapshot.value?.allKeys)! as? [String]{
self.snusBrandsArray = allProducts
self.productstable.reloadData()
}
}
})
Related
I am trying to migrate UIKit Views in my app to SwiftUI. One of the central elements in my app is a UICollectionView. I am embedding the SwiftUI views using a UIHostingController - so far so good.
I am wondering, since my cells are reusable, what happens to the UIHostingController when the cell is recycled?
Do I need to take it out of the controller chain?
If I need to, what is the best way to do so? (storing the UIHostingController in the cell?)
Eg. a header view looks like this so far:
class HeaderViewCell: UICollectionReusableView {
var layoutAttributes:GroupHeaderViewLayoutAttributes = GroupHeaderViewLayoutAttributes()
public func attachContent(model:GroupHeaderModel, controller:UIViewController){
let view = GroupHeaderView(model: model, layoutAttributes: self.layoutAttributes)
let hostingController = UIHostingController(rootView: view)
if let contentView = hostingController.view {
controller.addChild(hostingController)
self.addSubviewAndConstrains(contentView)
}
}
override func prepareForReuse() {
self.subviews.forEach { $0.removeFromSuperview() }
layoutAttributes = GroupHeaderViewLayoutAttributes()
}
override func apply(_ layoutAttributes: UICollectionViewLayoutAttributes) {
if let attributes = layoutAttributes as? TileViewLayout.HeaderViewAttributes {
self.layoutAttributes.topBarHeight = attributes.topBarHeight
self.layoutAttributes.indicatorWidth = attributes.indicatorWidth
}
}
}
I am just starting using Vapor 4, and I created a POC to test how to save a Model into a local mySQL database.
Here is the code I am using for the controller that is supposed to save the model to the database.
public class ProductController {
static func create(req: Request) throws -> HTTPStatus {
do {
let input = try req.content.decode(Product.self)
let product = Product(name: input.name, imageUrl: input.imageUrl, priceAmount: input.priceAmount, priceCurrencyCode: input.priceCurrencyCode, category: input.category)
let _ = input.create(on: req.db).map {
print("Product saved")
}
return HTTPStatus.ok
} catch {
return HTTPStatus.badRequest
}
}
For some reason, "Product saved" never gets printed, so the closure is never called.
When I check in the database, the table products is always empty.
Thank you in advance for your help!
Karim
Try saving the product instead of the input:
return product.create(on: req.db).map { print("Product saved") }
.transform(to: .ok)
I'm using the Rust csv crate to read CSV files. I want to create the option for the user to take x first records from the CSV.
Given a function like fn read_records(csv_reader: csv::Reader, max_records: Option<usize>) -> ?, I want to do the below:
use std::fs::File;
use std::io::BufReader;
use csv as csv_crate;
use self::csv_crate::StringRecordsIntoIter;
/// Read a csv, and print the first n records
fn read_csv_repro(
mut file: File,
max_read_records: Option<usize>,
) {
let mut csv_reader = csv::ReaderBuilder::new()
.from_reader(BufReader::new(file.try_clone().unwrap()));
let records: Box<StringRecordsIntoIter<std::io::BufReader<std::fs::File>>> = match max_read_records {
Some(max) => {
Box::new(csv_reader.into_records().take(max).into_iter())
},
None => {
Box::new(csv_reader.into_records().into_iter())
}
};
for result in records
{
let record = result.unwrap();
// do something with record, e.g. print values from it to console
let string: Option<&str> = record.get(0);
println!("First record is {:?}", string);
}
}
fn main() {
read_csv_repro(File::open("csv_test.csv").unwrap(), Some(10));
}
(gist)
I'm struggling with getting my code to work, with the below error from the compiler:
error[E0308]: mismatched types
--> src/main.rs:18:22
|
18 | Box::new(csv_reader.into_records().take(max).into_iter())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `csv::reader::StringRecordsIntoIter`, found struct `std::iter::Take`
|
= note: expected type `csv::reader::StringRecordsIntoIter<_>`
found type `std::iter::Take<csv::reader::StringRecordsIntoIter<_>>`
How can I get the above code to work?
While Nate's answer works for this specific case, the more general solution here is to use trait objects. My impression is that this is what you were intending to do by using Box here. Otherwise, in Nate's solution, the use of Box is completely superfluous.
Here is code that uses trait objects without needing to do take(std::usize::MAX) (using Rust 2018):
use std::fs::File;
use std::io::BufReader;
/// Read a csv, and print the first n records
fn read_csv_repro(
file: File,
max_read_records: Option<usize>,
) {
let csv_reader = csv::ReaderBuilder::new()
.from_reader(BufReader::new(file.try_clone().unwrap()));
let records: Box<Iterator<Item=csv::Result<csv::StringRecord>>> =
match max_read_records {
Some(max) => {
Box::new(csv_reader.into_records().take(max).into_iter())
},
None => {
Box::new(csv_reader.into_records().into_iter())
}
};
for result in records
{
let record = result.unwrap();
// do something with record, e.g. print values from it to console
let string: Option<&str> = record.get(0);
println!("First record is {:?}", string);
}
}
fn main() {
read_csv_repro(File::open("csv_test.csv").unwrap(), Some(10));
}
You have to take(std::usize::MAX) when max_records is None. It's annoying, but both iterators have to have the same type to be stored in the same variable. Also, the .intoIter()'s that you added have no effect, as you were calling them on iterators.
fn read_csv_repro(file: File, max_read_records: Option<usize>) {
let mut csv_reader = csv::Reader::from_reader(BufReader::new(file));
let records: Box<std::iter::Take<StringRecordsIntoIter<std::io::BufReader<std::fs::File>>>> = match max_read_records {
Some(max) => {
Box::new(csv_reader.into_records().take(max))
},
None => {
Box::new(csv_reader.into_records().take(std::usize::MAX))
}
};
}
I know that the title sounds complicated, but the question is not.
I have this Swift code:
class MyClass {
let helloWorld: (check: Bool)->()
init(helloWorld: (check: Bool)->()) {
self.helloWorld = helloWorld
}
}
let instanceOfMyClass = MyClass(helloWorld: (check: Bool) -> {
})
This gives me an error. What is the correct syntax for the last instruction?
Thanks!
You can use this:
let instanceOfMyClass = MyClass(helloWorld: { (check) in println(check) } )
but if the closure is the last argument, you can use the trailing closure syntax, where the closure is written outside of the function (init in your case) parenthesis - which is easier to read:
let instance = MyClass() { (check) in
println(check)
}
There are other shortcuts to define closures, such as this one:
let instance2 = MyClass() { println($0) }
but I suggest you to read the entire closure chapter in the official swift book.
Note: in my code above replace println(...) with your actual processing
I'm working on something that involved using the Bit.ly API, and allow the user to select theformat (Text, XML, Json) the text & XML are completed. This is the Json result that is returned when you shorten a URL:
{
"status_code": 200,
"status_txt": "OK",
"data":
{
"long_url": "http:\/\/panel.aspnix.com\/Default.aspx?pid={Removed}",
"url": "http:\/\/rlm.cc\/gtYUEd",
"hash": "gtYUEd",
"global_hash": "evz3Za",
"new_hash": 0
}
}
And this C# code works just fine to parse it and get the short URL:
var serializer2 = new JavaScriptSerializer();
var values2 = serializer2.Deserialize<IDictionary<string, object>>(json);
var results2 = values2["data"] as IDictionary<string, object>;
var shortUrl2 = results2["url"];
expandedUrl = results2["url"].ToString();
return results2["url"].ToString();
Now here's the Json sent back when expanding a URL:
{
"status_code": 200,
"status_txt": "OK",
"data":
{
"expand":
[
{
"short_url": "http:\/\/rlm.cc\/gtYUEd",
"long_url": "http:\/\/panel.aspnix.com\/Default.aspx?pid={Removed}",
"user_hash": "gtYUEd",
"global_hash": "evz3Za"
}
]
}
}
Ad that's where my problem begins, how can I change my current C# to be able to handle both scenarios, because as you can see their vastly different from each other. Any ideas?
I usually use Json.NET to cherrypick values out of JSON documents. The syntax is very concise. If you reference NewtonSoft.Json.dll and use Newtonsoft.Json.Linq, you can write the following:
var job = JObject.Parse(jsonString);
if (job["data"]["expand"] == null)
{
Console.WriteLine((string)job["data"]["url"]);
}
else
{
Console.WriteLine((string)job["data"]["expand"][0]["long_url"]);
}
If jsonString is:
string jsonString = #"{""status_code"": 200, ""status_txt"": ""OK"", ""data"": {""long_url"": ""http:\/\/panel.aspnix.com\/Default.aspx?pid={Removed}"", ""url"": ""http:\/\/rlm.cc\/gtYUEd"", ""hash"": ""gtYUEd"", ""global_hash"": ""evz3Za"", ""new_hash"": 0 }}";
the routine will display http://rlm.cc/gtYUEd.
If jsonString is:
string jsonString = #"{""status_code"": 200, ""status_txt"": ""OK"", ""data"": { ""expand"": [ { ""short_url"": ""http:\/\/rlm.cc\/gtYUEd"", ""long_url"": ""http:\/\/panel.aspnix.com\/Default.aspx?pid={Removed}"", ""user_hash"": ""gtYUEd"", ""global_hash"": ""evz3Za"" } ] } }";
the routine will display http://panel.aspnix.com/Default.aspx?pid={Removed}.
Not sure I got your problem. Why aren't you testing, if you got a shortening result or a expanding result? Since they are different, this could easily be done via simple 'if ()' statements:
if (results2.ContainsKey("expand")) {
// handle the expand part
} else {
// handle the shorten part
}
Assuming that the provider is consistent with which form it sends, do you need to have code that handles both? It should be direct to handle each individually.
If you can't know ahead of time which format you will get back, you can do the following:
if (results2.ContainsKey("expand"))
{
//Second example
}
else
{
//First example
}