Parsing Iterative JSON from Firebase to Flutter - json

I have data saved into Realtime Firebase as an iterative JSON as shown in the picture.
Realtime Firebase data
[
{
"name": "Math",
"subMenu": [
{
"name": "Math1",
"subMenu": [
{
"name": "Math 1.1"
},
{
"name": "Math 1.2",
"subMenu": [
{
"name": "Math 1.2.1",
"subMenu": [
{
"name": "Math 1.2.1.1"
},
{
"name": "Math 1.2.1.2"
}
]
},
{
"name": "Math 1.2.2"
}
]
}
]
},
{
"name": "Math2"
},
{
"name": "Math3",
"subMenu": [
{
"name": "Math 1.3.1"
},
{
"name": "Math 1.3.2"
}
]
}
]
},
{
"name": "Marketing",
"subMenu": [
{
"name": "Promotions",
"subMenu": [
{
"name": "Catalog Price Rule"
},
{
"name": "Cart Price Rules"
}
]
},
{
"name": "Communications",
"subMenu": [
{
"name": "Newsletter Subscribers"
}
]
}
]
}
]
How the JSON look like in Realtime Firebase
'Click the image'
datamodel.dart
class Menu {
String? name;
int? font;
List<Menu>? subMenu = [];
Menu({this.name, this.subMenu, this.font});
Menu.fromJson(Map<String, dynamic> json) {
font = json['font'];
name = json['name'];
if (json['subMenu'] != null) {
json['subMenu'].forEach((v) {
subMenu?.add(Menu.fromJson(v));
});
}
}
}
My goal is to build a multilevel list view in Flutter that reflexes iterative JSON structure. So, I implemented a method that returns List<Menu>, and then pass it to a Futurebuilder to build a multilevel list View.
The method.
final ref = FirebaseDatabase.instance.ref();
Future<List<Menu>> firebaseCalls(DatabaseReference ref) async {
final snapshot = await ref.child('Task').get();
final jsondata = snapshot.value as Map<String, dynamic>;
final list = json.decode(jsondata) as List<dynamic>; // Error Location
return list.map((e) => Menu.fromJson(e)).toList();
}
and I got the following
The Error
error: The argument type 'Map<String, dynamic>' can't be assigned to the parameter type 'String'. (argument_type_not_assignable at [flutter_multilevel_list_from_json] lib\main.dart:28)
tried to change the list type to List<dynamic> but still give me an error.

json.decode() takes a String as input, and you are passing a Map<String,dynamic> into it.
That is your problem, not that you are trying to cast it to a List<dynamic>

May be this will be helpful (jsondata as List).map((e) => Menu.fromJson(e)).toList();

Related

initialize json file data as a TypeScript Map

as a young typescript padawan
i am trying to parse mock data from a json witch involves initializing a Map<string, MenuPageData>
and i get an error (attached below)
i would like to be able to supply the correct data format in the json or map it properly from the existing data.
here is the error:
here is the code:
export interface MenuItem {
data: {
id: string;
name: string;
currency?: string;
imageUrl?: string;
description?: string;
price?: number;
};
}
export interface MenuPageData {
pageName: string;
menuItems: MenuItem[];
}
export interface MenuPageDataCollection {
menuPages: Map<string, MenuPageData>;
}
the error is comming from "(pagesDataMock.menuPages)"
const dataCollection: MenuPageDataCollection = { menuPages: new Map<string, MenuPageData>(pagesDataMock.menuPages) };
export const menuPagesCollection: () => MenuPageDataCollection = (): MenuPageDataCollection => {
return dataCollection;
};
and here is the json source:
{
"menuPages": [
"mealPage1",
{
"pageName": "menuPage1",
"menuItems": [
{
"data": {
"id": "null0",
"name": "meal",
"currency": "EUR",
"imageUrl": "../images/greenHand.jpg",
"description": "tasty",
"price": 12
}
},
{
"data": {
"id": "null0",
"name": "meal",
"currency": "EUR",
"imageUrl": "../images/greenHand.jpg",
"description": "tasty",
"price": 12
}
}
]
},
"mealPage2",
{
"pageName": "menuPage1",
"menuItems": [
{
"data": {
"id": "null0",
"name": "meal",
"currency": "EUR",
"imageUrl": "../images/greenHand.jpg",
"description": "tasty",
"price": 12
}
},
{
"data": {
"id": "null0",
"name": "meal",
"currency": "EUR",
"imageUrl": "../images/greenHand.jpg",
"description": "tasty",
"price": 12
}
}
]
}
]
}
i would appreciate and feedback, i tried several different ways of doing it but now 3-4 days passed by and i am running on empty of understanding
Map is a rather strong constraint that is not representable in JSON as is. First you'll have to validate the input is satisfying the requirements for your Map<string, MenuPageData>. Then to make it understandable by TS wrap in into type guard or type assert function. And finally convert it into the actual Map object yourself.
Simplified example:
interface IFace {
prop: string
}
interface Res {
title: string
ifaceMap: Map<string, IFace>
}
interface ResJSON {
title: string
ifaceMap: { [K in string]: IFace }
}
function assertResponse(json: unknown): asserts json is ResJSON {
...
}
function convert2Res(res: ResJSON): Res {
const { title, ifaceMap } = res
const map = new Map()
for(let key in ifaceMap) map.set(key, ifaceMap[key])
return { title, ifaceMap: map }
}
assertResponse(goodResponse)
const mapRes = convert2Res(goodResponse)
TS playground
In case you have full control of the source json and absolutely sure it may never be misshaped you may completely skip the assert part and feed the response (forcibly asserted to ResJSON type) right into convert2Res.

Dwg comparison through design automation

I would like to know if it is possible, and if yes, how can I achieve dwg comparison through the design automation? I there a way to create a comparison activity accepting 2 dwg in input, and post a boolean as output?
Yes you can create an activity accepting two drawings.
Following activity JSON uses an in-built compare and output the result diff drawing.
Sample Activity Json
{
"HostApplication": "",
"RequiredEngineVersion": "23.0",
"Parameters": {
"InputParameters": [
{
"Name": "HostDwg",
"LocalFileName": "$(HostDwg)"
},
{
"Name": "ToCompareWith",
"LocalFileName": "ToCompareWith.dwg"
}
],
"OutputParameters": [
{
"Name": "Result",
"LocalFileName": "output.dwg"
}
]
},
"Instruction": {
"CommandLineParameters": null,
"Script": "COMPAREINPLACE\nON\n-COMPARE\n\nToCompareWith.dwg\n_SAVEAS\n\noutput.dwg\n"
},
"Id": "FPDCompare"
}
Workitem Json
{
"Arguments": {
"InputArguments": [
{
"Resource": "https://madhukar-fda.s3.us-west-2.amazonaws.com/Kitchens1.dwg",
"Name": "HostDwg"
},
{
"Resource": "https://madhukar-fda.s3.us-west-2.amazonaws.com/Kitchens2.dwg",
"Name": "ToCompareWith"
}
],
"OutputArguments": [
{
"Name": "Result",
"HttpVerb": "POST"
}
]
},
"ActivityId": "FPDCompare"
}
If you are using your own custom compare logic, you can output the
results to txt file or json file.
Activity Json
{
"HostApplication": "",
"RequiredEngineVersion": "23.0",
"Parameters": {
"InputParameters": [
{
"Name": "HostDwg",
"LocalFileName": "$(HostDwg)"
},
{
"Name": "ToCompareWith",
"LocalFileName": "ToCompareWith.dwg"
}
],
"OutputParameters": [
{
"Name": "Result",
"LocalFileName": "output.txt"
}
]
},
"Instruction": {
"CommandLineParameters": null,
"Script": "ISDWGSIMILAR\nToCompareWith.dwg\n"
},
"AppPackages":["Compare"],
"Version": 1,
"Id": "Compare"
}
Workitem Json
{
"Arguments": {
"InputArguments": [
{
"Resource":"https://madhukar-fda.s3.us-west-2.amazonaws.com/Kitchens.dwg",
"Name": "HostDwg"
},
{
"Resource":"https://madhukar-fda.s3.us-west-2.amazonaws.com/Kitchens1.dwg",
"Name": "ToCompareWith"
}
],
"OutputArguments": [
{
"Name": "Result",
"HttpVerb": "POST"
}
]
},
"ActivityId": "Compare"
}
Note: In the script argument - "ISDWGSIMILAR" is a custom command where you will process two drawings, the first one will be current and second one is the drawing to which you are willing compare [ToCompareWith]
Custom NET Command
[CommandMethod("FDACOMMANDS", "ISDWGSIMILAR", CommandFlags.Transparent)]
public static void CompareDrawing()
{
var doc = Application.DocumentManager.MdiActiveDocument;
var db = doc.Database;
var ed = doc.Editor;
var promptResult = ed.GetString("Select Drawing To Compare With");
if (promptResult.Status != PromptStatus.OK) return;
var drawingToCompareWith = promptResult.StringResult;
ed = Application.DocumentManager.MdiActiveDocument.Editor;
using (OpenCloseTransaction o = new OpenCloseTransaction())
{
/*
{
Here your logic code to compare two drawings
}
*/
/*output.txt / json is pushed to your cloud storage as provided in workitem json*/
using (var writer = File.CreateText("output.txt"))
{
if (b != null) /*b value is result of your compare*/
{
writer.WriteLine("TRUE Drawings are same");
}
else writer.WriteLine("FALSE Drawings aren't same");
}
}
}

JSON transformation in node.js

I want to transform my data from one json structure to another. What is the best way to do it?
Here is my original resource (customer) structure is:
{
"id": "123",
"data": {
"name": "john doe",
"status": "active",
"contacts": [
{
"email": "john#email.com"
},
{
"phone": "12233333"
}
]
}
}
I want to change it to:
{
"id": "123",
"name": "john doe",
"status": "active",
"contacts": [
{
"email": "john#email.com"
},
{
"phone": "12233333"
}
]
}
Keeping in mind that I might have an array of resources(customers) being returned in GET /customers cases. I want to change that to an array of new data type.
If customer object is array of object then below will help you to get desire format result
var result = customerObj.map(x => {
return {
id: x.id,
name: x.data.name,
status: x.data.status,
contacts: x.data.contacts
};
});
here I have used Object.assign() it will be helpful to you
var arr={
"id": "123",
"data": {
"name": "john doe",
"status": "active",
"contacts": [
{
"email": "john#email.com"
},
{
"phone": "12233333"
}
]
}
}
arr=Object.assign(arr,arr.data);
delete arr['data'];
console.log(arr);
You have to Json.parse the json into variable, and then loop through the array of objects, changes the object to the new format, and then JSON.stringify the array back to json.
Example code
function formatter(oldFormat) {
Object.assign(oldFormat, oldFormat.data);
delete oldFormat.data;
}
let parsedData = JSON.parse(Oldjson);
//Take care for array of results or single result
if (parsedData instanceof Array) {
parsedData.map(customer => formtter(customer));
} else {
formatter(parsedData);
}
let newJson = JSON.stringify(parsedData);
console.log(newJson);
Edit
I made the formatter function cleaner by using Kalaiselvan A code

evaluating json object returned from controller and attaching it to prepopulate attribute of tokeninput

I am using loopjs tokeninput in a View. In this scenario I need to prePopulate the control with AdminNames for a given Distributor.
Code Follows :
$.getJSON("#Url.Action("SearchCMSAdmins")", function (data) {
var json=eval("("+data+")"); //doesnt work
var json = {
"users": [
eval("("+data+")") //need help in this part
]
}
});
$("#DistributorCMSAdmin").tokenInput("#Url.Action("SearchWithName")", {
theme: "facebook",
preventDuplicates: true,
prePopulate: json.users
});
There is successful return of json values to the below function. I need the json in the below format:
var json = {
"users":
[
{ "id": "1", "name": "USER1" },
{ "id": "2", "name": "USER2" },
{ "id": "3", "name": "USER3" }
]
}

How to parse JSON to List with Maps in Gson?

I have the following Java Classes:
public class ModuleParsed {
String id_component;
String id_instance;
Map<ModuleParam, ModuleParam> input;
Map<ModuleParam, List<ModuleParam>> output;
int id_paas;
}
and
public class ModuleParam {
String name;
Object type;
}
what should be the JSON expected to parse it as a List<ModuleParsed>?
listModules = gson.fromJson(br, new TypeToken<List<ModuleParsed>>() {}.getType());
Everything was ok until I introduced the input and output parameters.
EDIT
By doing the reverse process I have found the JSON should be something like
[
{
"id_component": "mod1",
"id_instance": "mod1_inst1",
"input": {
"moduleParam": {
"name": "param3",
"type": "obj3"
},
"moduleParam": {
"name": "param2",
"type": "obj2"
}
},
"id_paas": 1
},
{
"id_component": "mod2",
"id_instance": "mod2_inst1",
"input": {
"moduleParam": {
"name": "param3",
"type": "obj3"
},
"moduleParam": {
"name": "param2",
"type": "obj2"
}
},
"id_paas": 1
}
]
where the moduleParam elements were something like: parser.ModuleParam#36c51089
No matter how I name these elements I get the following error:
Exception in thread "main" com.google.gson.JsonParseException: Expecting object found: "moduleParam"
How can I obtain the class ModuleParsed with Gson?
Following #Brian's comment I realized I had no need to use complex objects as keys so this was my solution.
public class ModuleParsed {
String id_component;
String id_instance;
Map<String, ModuleParam> input;
Map<String, List<ModuleParam>> output;
int id_paas;
}
public class ModuleParam {
String name;
String id_module;
String id_instance;
}
for which I built the following JSON
[
{
"id_component": "mod1",
"id_instance": "mod1_inst1",
"input": {
"input1": {}
},
"output": {
"output1": [
{
"name": "input1",
"id_module": "mod2",
"id_instance": "mod2_inst1",
"type": "paramType"
},
{
"name": "input2",
"id_module": "mod2",
"id_instance": "mod2_inst1",
"type": "paramType"
}
],
"output2": []
},
"id_paas": 1
},
{
"id_component": "mod2",
"id_instance": "mod2_inst1",
"input": {
"input1": {
"name": "output1",
"id_module": "mod1",
"id_instance": "mod1_inst1",
"type": "paramType"
},
"input2": {
"name": "output1",
"id_module": "mod1",
"id_instance": "mod1_inst1",
"type": "paramType"
}
},
"output": {},
"id_paas": 1
}
]
The JSON was parsed correctly this time.