Unable to parse data from firebase in flutter - json

Here is the model I am using for the data.
Here is the Future I am using to extract the data.
Future<List<Topic>> getTopics(String subjectid) async {
var ref = db.collection('topics')
.where(
'subject',
isEqualTo: subjectid
);
var snapshot = await ref.get();
var data = snapshot.docs.map((s) => s.data());
var topics = data.map((d) => Topic.fromJson(d));
return topics.toList();
}
Here is how I have the data in firebase.
I am getting a error in the type cast:
type 'InternalLinkedHashMap<string, dynamic>' is not a subtype of type 'List<dynamic>?
When I try to print the topics.toList(), the print returns nothing.
I played around with my model, made sure all the columns are mapped correctly. My call for another collection works fine. But this one just won't work.

Related

Firestore data() method does not exist on JSON parsed document after JSON stringified

I am building a FlashCard website using NextJs and firebase. I have a homepage which I want to render server side and so I am using getServerSideProps. InsidegetServerSideProps function, I am fetching all the documents of the current user from firestore and is stored in an array and is returned as props as below:
export const getServerSideProps = async(ctx: GetServerSidePropsContext) {
let notes: DocumentData[];
// fetch documents here and populate notes array like so [doc,doc,doc,..]
// data() method works here and returns document fields
console.log(notes[0].data());
// NextJs throws error "`object` ("[object Object]") cannot be serialized as JSON. Please only return JSON serializable data types.", so I have to JSON.stringify() the notes
return {
props: {
notes: JSON.stringify(notes),
}
}
}
Below, I have my homepage where I parse the JSON string and have access to the notes, but now the data() method on the document does not exist/works and throws method does not exist errors. If I have to access the document fields, I have to use the dot operator on every property of the document till I reach the fields property which is nested deep down in the object as follows:
export default function Home({ notes }) {
let docs = JSON.parse(notes); // can access notes
// data() method throws function does not exist error
console.log(docs[0].data());
// I am only able to access document fields as below
console.log(docs[0]._document.data.value.mapValue.fields);
return (
<Layout>
<HomeContent notes={docs}/>
</Layout>
);
}
I have searched everywhere and found nothing that helped me why data() method won't work. If I directly fetch the documents inside the page component on client side, the data() method on the document returns its' fields. I don't know how using JSON serializations affect it. I would always prefer to use data() method to access fields than to go that deep plus I am planning to fetch data on server on other pages as well.
I would really appreciate if you can shed some light on it. It took all of my days time.
EDIT: The code that gets notes from firestore:
// inside getServerSideProps
let notes: DocumentData[] = null;
const getNotes = async(ref: DocumentReference < DocumentData > , uid: string) => {
let tempNotes = [];
const categoriesSnapshot = await getDoc < DocumentData > (ref);
const categoriesObject = categoriesSnapshot.data();
// return if user doesn't have any documents
if (!categoriesObject) {
return;
}
const promises: [] = categoriesObject.categories.map((category: string) => {
const userCategoriesRef = collection(database, 'CategoryCollection', uid, category);
return getDocs(userCategoriesRef); // returns a promise
});
const allQuerySnapshots = await Promise.all < DocumentData > (promises);
allQuerySnapshots.forEach((querySnapshot) => {
tempNotes.push(...querySnapshot.docs);
});
notes = tempNotes;
}
const categoryDocRef = doc(database, "CategoryCollection", uid);
await getNotes(categoryDocRef, uid);

Merging several JSON files in TypeScript

I am currently tasked with finding the amount of times a specific email has contacted us. The contacts are stored in JSON files and the key should be "email".
The thing is there are potentially infinite JSON files so I would like to merge them in to a single object and iterate to count the email frequency.
So to be clear I need to read in the JSON content. Produce it as a log
consume the message
transform that message into a tally of logs per email used.
My thought process may be wrong but I am thinking I need to merge all JSON files into a single object that I can then iterate over and manipulate if needed. However I believe I am having issues with the synchronicity of it.
I am using fs to read in (I think in this case 100 JSON files) running a forEach and attempting to push each into an array but the array comes back empty. I am sure I am missing something simple but upon reading the documentation for fs I think I just may be missing it.
const fs = require('fs');
let consumed = [];
const fConsume = () => {
fs.readdir(testFolder, (err, files) => {
files.forEach(file => {
let rawData = fs.readFileSync(`${testFolder}/${file}`);
let readable = JSON.parse(rawData);
consumed.push(readable);
});
})
}
fConsume();
console.log(consumed);
For reference this is what each JSON object looks like, and there are several per imported file.
{
id: 'a7294140-a453-4f3c-91b6-210819e2c43e',
email: 'ethan.hernandez#microsoft.com',
message: 'successfully handled skipped operation.'
},
fs.readdir() is async, so your function returns before it executes the callback. If you want to use synchronous code here, you need to use fs.readdirSync() instead:
const fs = require('fs');
let consumed = [];
const fConsume = () => {
const files = fs.readdirSync(testFolder)
files.forEach(file => {
let rawData = fs.readFileSync(`${testFolder}/${file}`);
let readable = JSON.parse(rawData);
consumed.push(readable);
});
}
fConsume();
console.log(consumed);

Getting error when printing json array in EJS variable on console

Guys I am using expressjs, ejs to develop an online shopping website.
Scenario
In order to display products {name, description, imageUrl} I am iterating with the help of ejs control-flow on the webpage.
I am sending an array that contains all the details about each product in JSON format. (from server)
on the client-side when I try to access this array of jsons I get the following error.
(index):266 Uncaught SyntaxError: Invalid or unexpected token
When I opened the sources tab in google chrome it, showed me this
At line number 266. I believe that it is taking this as a string by wrapping the array in double quotes.?
Could anyone tell me what's going wrong with this code?
And by the way, is how I trying to print the array on chrome console
<script>
const data = JSON.parse("<%- products %>");
console.log(data);
</script>
where products are an array of jsons
Backend home route which is sending the JSON array is as follows
router.get("/", async (req, res) => {
let catalogInformation = {};
//getAllProducts returns array of json from the database
const products = await getAllProducts();
catalogInformation.products = products;
userData = {
email: null,
username: null,
};
catalogInformation.userData = userData;
if (req.session.userInformation != null || req.session.userInformation != undefined) {
catalogInformation.userData = req.session.userInformation;
} else {
catalogInformation.userData = {
email: null,
username: null,
};
}
// res.render("catalog", userData);
res.render("catalog", catalogInformation);
return;
});
getAllProducts() method
const getAllProducts = async () => {
const Product = mongoose.model("product", productSchema);
const allProducts = await Product.find();
return allProducts;
};
You don't need to use JSON.parse. Just output the JSON directly:
var data = <%- products %>;
I wouldn't suggest making an AJAX call because you'd be handling 2 requests instead of 1.

How can i get a single response using linq

I have the following API code to get a single result response but i get error json.net complaining
when i remove this line var Product = prdList .FirstOrDefault(a => a.ID == productID); and return Json(prdList); it works fine but return every row in a table. how can i get a single record?
Here is the code
[HttpGet("{productID}")]
public async Task<IActionResult> Getproduct(int productID)
{
var prdList = (await rpsService.Getrps(productID)).ToList();
var Product = prdList .FirstOrDefault(a => a.ID == productID);
return Json(Product);
}
Here is the error im getting, i retrive the right information but i get error when i load the page
JsonSerializationException: Cannot deserialize the current JSON object
(e.g. {"name":"value"}) into type 'System.Collections.Generic.IList`1
Project name' because the type requires a JSON array (e.g. [1,2,3]) to
deserialize correctly. To fix this error either change the JSON to a
JSON array (e.g. [1,2,3]) or change the deserialized type so that it
is a normal .NET type (e.g. not a primitive type like integer, not a
collection type like an array or List) that can be deserialized
from a JSON object. JsonObjectAttribute can also be added to the type
to force it to deserialize from a JSON object. Path 'productID', line
1, position 13.
I tried this working fine but display all rows
[HttpGet("{productID}")]
public async Task<IActionResult> GetProduct(int productID)
{
var prdList = (await rpsService.Getrps(productID)).ToList();
return Json(prdList );
}
you can directly apply condition while fetching list as mention below.
var prdList = (await rpsService.Getrps(productID)).ToList().FirstOrDefault();
Try this
var Product = prdList.Where(a => a.ID == productID).FirstOrDefault();
or
var prdList = (await rpsService.Getrps(productID)).ToList().FirstOrDefault();
return Json(prdList);

fetch data with flutter Receiver: null error

i try to fetch api json , here is the link https://api.myjson.com/bins/ut9kq
when i print the output before the loop it does get the data but after the list it give me error
"Unhandled Exception: NoSuchMethodError: The getter 'image' was called on null.
E/flutter (30730): Receiver: null
E/flutter (30730): Tried calling: image"
here is my code
List lists;
Future<List> getLists() async {
lists = new List();
await api.httpGet('bins/ut9kq').then((reponse) {
var data = jsonDecode(reponse.body);
print(data); // i get the json data => [{},{}..]
data.forEach((l) {
lists.add(ArticleModal().fromJson(l));
});
// print(lists[0].image);//Receiver: null
});
return lists;
}
You are using both approaches for future handling, .then callbacks and async and await. Try the following, you can wrap these around try/catch blocks for error handling.
Future<List<ArticleModal>> getLists() async {
lists = new List();
var response = await http.get('bins/ut9kq');
// a switch may be used for a wider range of codes
if (response.statusCode == 200) {
var decodedResponse = json.decode(response.body);
print(decodedResponse);
//if response is a collection
var listAricleModal = (decodedResponse as List).map((collectionElement) => ArticleModal.fromJson(collectionElement)).toList();
return listAricleModal;
}
//Your future is an empty collection
return [];
}
And to properly answer your question, image is called on null is quite obvious message.
At some point you have an image field, that object is not created. Probably is the object in the list, so two things may be happening:
List is empty, so nothing to call image on.
There is a problem when calling fromJson.
Either way, use the debugger and set breakpoints on each method first line to clearly understand what is happening.
If map function is tricky to debug, use a plain for loop until you know where the bug is.
Check out this series of videos from Google.
https://youtu.be/vl_AaCgudcY
Also official docs: https://dart.dev/codelabs/async-await