adding elements to json string(array) FLUTTER - json

I have a JSON string, inside of it I have an array, I want to add data to it as I tried to do it below:
String myJSON = '{"listOfSubtasks":["dasd","dadd","dadsd"]}';
arrayToStringAndBack(addElement) async {
var json = jsonDecode(myJSON);
var getArray = json['listOfSubtasks']; //returns [dasd,dadd,dadsd]
setState(() {
getArray.add(addElement);
});
// as I want to push it to a db I convert [dasd,dadd,dadsd] to a String ["dasd","dadd","dadsd"]
String arrayToString = jsonEncode(getArray);
print(arrayToString);
}
...
textfieldform
- onSaved: (val) {
subtasks = val;
arrayToStringAndBack(val);
},
...
When I type smth and click on a submit button an element is added to the end of an array but once I try to do it one more time, to add an element, the last element that was added changes to one I created.
I want to add as many elements as I want, not just a single one
Solved
var arrayOfSubTasks = [];
arrayToStringAndBack(addElement, arr) async {
var json = jsonDecode(myJSON);
var getArray = json['listOfSubtasks'];
setState(() {
getArray.add(arr);
});
String arrayToString = jsonEncode(getArray);
print(arrayToString);
}
...
onSaved: (val) {
subtasks = val;
setState(() {
arrayOfSubTasks.add(val);
});
arrayToStringAndBack(val, arrayOfSubTasks);
},

You can treat your list of subtasks as a List to be able to add String with List.add(). Then encode the List to a json with jsonEncode()

Related

Put Set of object to JSON

How can put a Set of object to Json. Seems like that code is not good at all
Future<File> writeBasket(Set<Item> listItems) async {
final file = await _localFile;
var jsonString = listItems.map((Item item) {
return jsonEncode(item);
});
return file.writeAsString(jsonString.toString());
}
Make sure that Item has a toJson method, for example:
class Item {
String val1;
Item(this.val1);
Map<String, dynamic> toJson() => {'val1': val1};
}
The nearest equivalent to a set in json is a list, so convert your set to a list before calling json.encode.
Set<Item> items = Set<Item>()..add(Item('xxx'))..add(Item('yyy'));
String j = json.encode(items.toList());
print(j);
prints [{"val1":"xxx"},{"val1":"yyy"}] which you could save to your file.

Flutter - Dart variables lost and keep getting reinitialized

I'm trying out things with Flutter right now. But my variables keep getting reinitialised when accessed from another class.
I'm using json parsing and i need two parts of my request. The "Relatorio" part and the "Mensagem" part.
to parse this json i'm doing this:
List<RelatorioProdutos> parseRelatorioPorProduto(String responseBody) {
final parsed = json.decode(responseBody);
var relatorio = parsed['Relatorio'];
var mensagem = parsed['Mensagem'];
print (mensagem); // Here the variable returns well,
//but when i need it in other class i receive null.
return relatorio.map<RelatorioProdutos>((json) => new RelatorioProdutos.fromJson(json)).toList();
}
class RelatorioProdutos {
String CodigoProduto;
var QtdVendida;
var TotalVendas;
String Descricao;
RelatorioProdutos({this.CodigoProduto, this.QtdVendida, this.TotalVendas, this.Descricao,});
factory RelatorioProdutos.fromJson(Map json) {
//returns a List of Maps
return new RelatorioProdutos(
CodigoProduto: json['CodigoProduto'] as String,
QtdVendida: json['QtdVendida'],
TotalVendas: json['TotalVendas'],
Descricao: json['Descricao'] as String,
);
}
}
I want to use this 'mensagem' variable in another class to show the error for user, but i always receive 'null'.
i already tried setState but it reloads my json and i dont want to request the RestServer again.
Thanks from now!
If I understand correctly, you want to access a local variable of a function from another class. I don't think it's possible.
One way to do it, would be to wrap your response in another object containing the response, and this variable:
List<Response<RelatorioProdutos>> parseRelatorioPorProduto(
String responseBody) {
final parsed = json.decode(responseBody);
var relatorio = parsed['Relatorio'];
var mensagem = parsed['Mensagem'];
print(mensagem); // Here the variable returns well,
//but when i need it in other class i receive null.
return relatorio
.map((json) => new Response<RelatorioProdutos>(
new RelatorioProdutos.fromJson(json), mensagem))
.toList();
}
class RelatorioProdutos {
String CodigoProduto;
var QtdVendida;
var TotalVendas;
String Descricao;
RelatorioProdutos({
this.CodigoProduto,
this.QtdVendida,
this.TotalVendas,
this.Descricao,
});
factory RelatorioProdutos.fromJson(Map json) {
//returns a List of Maps
return new RelatorioProdutos(
CodigoProduto: json['CodigoProduto'] as String,
QtdVendida: json['QtdVendida'],
TotalVendas: json['TotalVendas'],
Descricao: json['Descricao'] as String,
);
}
}
class Response<T> {
const Response(
this.value,
this.errorMessage,
);
final T value;
final String errorMessage;
bool get hasError => errorMessage != null;
}
In this example I created a Response object that can contains both the response value and an error message.
In the parseRelatorioPorProduto, instead of returning the relatorio, I changed the return type to Response<RelatorioProdutos> in order to have access to the value and the error message from any class which call this function.
Thanks Letsar, i tried yout ideia but i get a lot of others erros.
To solve this problem i used this:
List<RelatorioProdutos> parseRelatorioPorProduto(String responseBody) {
final parsed = json.decode(responseBody);
var relatorio = parsed['Relatorio'];
var mensagem = parsed['Mensagem'];
if(mensagem[0].toString().substring(16,17) == "0"){
List<RelatorioProdutos> asd = new List();
RelatorioProdutos aimeudeus = new RelatorioProdutos(Descricao: mensagem[0].toString(), CodigoProduto: "a", TotalVendas: 0, QtdVendida: 0);
asd.add(aimeudeus);
return asd;
}else{
return relatorio.map<RelatorioProdutos>((json) => new RelatorioProdutos.fromJson(json)).toList();
}
}

Decypher ES6 const destructuring declaration

Can someone help me decypher this ES6 statement?
const {
isFetching,
lastUpdated,
items: posts
} = postsByReddit[selectedReddit] || {
isFetching: true,
items: []
}
I pulled it from the Redux async example - https://github.com/reactjs/redux/blob/master/examples/async/containers/App.js#L81
The code is simply declaring three constants, getting them from similarly named properties on an object if it is non-empty, otherwise get them from an object literal that acts as default values.
I trust that you are confused over the object like syntax rather than the const keyword.
var|let|const { ... } = ... is an object destructuring declaration.
var|let|const [ ... ] = ... is an array destructuring declaration.
Both are short hand for "break down right hand side and assign to left hand side".
Destructuring can be done on array or object using different brackets.
It can be part of a declaration or as stand-alone assignment.
const { isFetching } = obj; // Same as const isFetching = obj.isFetching
var [ a, b ] = ary; // Same as var a = ary[0], b = ary[1]
[ a ] = [ 1 ]; // Same as a = 1
For object destructuring, you can specify the property name.
For array, you can skip elements by leaving blank commas.
Destructuring can also form a hierarchy and be mixed.
const { items: posts } = obj; // Same as const posts = obj.items
var [ , , c ] = ary; // Same as var c = ary[2]
let { foo: [ { bar } ], bas } = obj; // Same as let bar = obj.foo[0].bar, bas = obj.bas
When destructuring null or undefined, or array destructure on non-iterable, it will throw TypeError.
Otherwise, if a matching part cannot be found, its value is undefined, unless a default is set.
let { err1 } = null; // TypeError
let [ err3 ] = {}; // TypeError
let [ { err2 } ] = [ undefined ]; // TypeError
let [ no ] = []; // undefined
let { body } = {}; // undefined
let { here = this } = {}; // here === this
let { valueOf } = 0; // Surprise! valueOf === Number.prototype.valueOf
Array destructuring works on any "iterable" objects, such as Map, Set, or NodeList.
Of course, these iterable objects can also be destructed as objects.
const doc = document;
let [ a0, a1, a2 ] = doc.querySelectorAll( 'a' ); // Get first three <a> into a0, a1, a2
let { 0: a, length } = doc.querySelectorAll( 'a' ); // Get first <a> and number of <a>
Finally, don't forget that destructuring can be used in any declarations, not just in function body:
function log ({ method = 'log', message }) {
console[ method ]( message );
}
log({ method: "info", message: "This calls console.info" });
log({ message: "This defaults to console.log" });
for ( let i = 0, list = frames, { length } = frames ; i < length ; i++ ) {
console.log( list[ i ] ); // Log each frame
}
Note that because destructuring depends on left hand side to specify how to destructre right hand side,
you cannot use destructring to assign to object properties.
This also excludes the usage of calculated property name in destructuring.
As you have seen, destructuring is a simple shorthand concept that will help you do more with less code.
It is well supported in Chrome, Edge, Firefox, Node.js, and Safari,
so you can start learn and use it now!
For EcmaScript5 (IE11) compatibility, Babel and Traceur transpilers
can turn most ES6/ES7 code into ES5, including destructuring.
If still unclear, feel free to come to StackOverflow JavaScript chatroom.
As the second most popular room on SO, experts are available 24/7 :)
This is an additional response to the already given. Destructuring also supports default values, which enables us to simplify the code:
const {
isFetching = true,
lastUpdated,
items = []
} = postsByReddit[selectedReddit] || {};
Basically:
var isFecthing;
var lastUpdated;
var posts;
if (postsByReddit[selectedReddit]) {
isFecthing = postsByReddit[selectedReddit].isFecthing;
lastUpdated = postsByReddit[selectedReddit].lastUpdated;
posts = postsByReddit[selectedReddit].items.posts;
} else {
isFecthing = true;
items = [];
}

AngularJS - Create dynamic properties to an object/model from json

OK, we all know this works:
vm.myObject = {
required : "This field requires data",
.....
}
But how can I create that same object dynamically when the property 'keys' and 'values' come from a json file, eg:
json:
[
{ "key" :"required", "value": "This field requires data"},
.....
]
service:
var myObject = {}
DynamicObjSvc.get()
.success(function(data){
data.forEach(function(item){
// pass each key as an object property
// and pass its respective value
?????????
})
.....
UPDATE:
Kavemen was mostly correct, this turned out to be the solution:
var myObject = {};
DynamicObjSvc.all()
.success(function(data){
angular.forEach(data, function(msg) {
myObject[msg.key] = msg.value; <-- his answer was incorrect here
});
$fgConfigProviderRef.validation.message(myObject);
})
.error(function(err){
console.log(err.message);
})
You can use angular.forEach and the bracket notation for setting (and getting) object properties in Javascript
var myObject = {}
DynamicObjSvc.get().success(
function(data) {
angular.forEach(data, function(value, key) {
myObject[key] = value;
});
}
);
See also Working with Objects from MDN
EDIT
I see now that your data is really an array of objects, not just a single object, so yes, the code above could lead you astray.
In any case, the method of setting an object's properties dynamically using the bracket notation is sound; the loop could be reworked to handle your data array as such:
//we have an array of objects now
var myObjects = [];
DynamicObjSvc.get().success(
function(data) {
//for each object in the data array
for(var i = 0; i < data.length; i++) {
//create and populate a new object for the ith data element
var newObject = {};
angular.forEach(data[i], function(value, key) {
newObject[key] = value;
});
//and add it to the overall collection
myObjects.push(newObject);
}
}
);

Create an instance of an object from a String/Symbol without the Class in Dart?

I know that it is possible to create an instance from a symbol like is shown in this link:
Create an instance of an object from a String in Dart?
But this doesn't work for me since what I want to do is create an instance without having the class.
This problem is caused because I have One class with an internal List:
class MyNestedClass {
String name;
}
class MyClass {
int i, j;
String greeting;
List<MyNestedClass> myNestedClassList;
}
And I want to convert a map to this class:
{
"greeting": "hello, there",
"i": 3,
"j": 5,
"myNestedClassList": [
{
"name": "someName1"
},{
"name": "someName2"
}
]
}
right now I am doing something like this:
static void jsonToObject(String jsonString, Object object) {
Map jsonMap = JSON.decode(jsonString); //Convert the String to a map
mapToObject(jsonMap, object); //Convert the map to a Object
}
static void mapToObject(Map jsonMap, Object object) {
InstanceMirror im = reflect(object); //get the InstanceMirror of the object
ClassMirror cm = im.type; //get the classMirror of the object
jsonMap.forEach((fieldNameStr, fieldValue) { // For each element in the jsonMap
var fieldName = new Symbol(fieldNameStr); // convert the fieldName in the Map to String
if (isPrimitive(fieldValue)) { // if fieldValue is primitive (num, string, or bool
im.setField(fieldName, fieldValue); //set the value of the field using InstanceMirror
} else if (fieldValue is List) { // else if the fieldValue is a list
ClassMirror listCm = (cm.declarations[fieldName] as VariableMirror).type; //get the class mirror of the list
var listReflectee = listCm.newInstance(const Symbol(''), []).reflectee; //create an instance of the field
for(var element in fieldValue) { //for each element in the list
if(!isPrimitive(element)) { // if the element in the list is a map (i.e not num, string or bool)
var listType = listCm.typeArguments[0]; //get the TypeMirror of the list (i.e MyNestedClass from List<MyNestedClass>)
//This is the line that doesn't work correctly
//It should be something like:
//
// ClassMirror.fromSymbol(listType.simpleName).newInstance(const Symbol(''), []);
//
var listObject = (listType as ClassMirror).newInstance(const Symbol(''), []); //create an instance of the specified listType
mapToObject(element, listObject); //convert the element to Object
}
listReflectee.add(element); //add the element to the list
};
} else { //else (the field value is a map
ClassMirror fieldCm = (cm.declarations[fieldName] as VariableMirror).type; // get the field ClassMirror from the parent declarations
var reflectee = fieldCm.newInstance(const Symbol(''), []).reflectee; //create an instance of the field
mapToObject(fieldValue, reflectee); // convert the fieldValue, which is a map, to an object
im.setField(fieldName, reflectee); // set the value of the object previously converted to the corresponding field
}
});
}
As you can see the lines that are not actually working are:
var listType = listCm.typeArguments[0]; //get the TypeMirror of the list (i.e MyNestedClass from List<MyNestedClass>)
var listObject = (listType as ClassMirror).newInstance(const Symbol(''), []); //create an instance of the specified listType
since they are creating an instance on localClassMirror and not on MyNestedClass. I'm looking for a method similar to:
ClassMirror.fromSymbol(listType.simpleName).newInstance(const Symbol(''), []);
you can see the full source code in the next URL:
DSON Source Code
If you have the full qualified name of the class you should be able to find the type using libraryMirror and then it should be similar to your linked question to create an instance.
I haven't done this myself yet and have not code at hand.
see also: how to invoke class form dart library string or file
An alternative approach would be to create a map at application initialization time where you register the supported types with their name or an id and look up the type in this map (this is like it's done in Go)