In this case I have class. Where I took a variable. Also I have a Json map. So I want to change Json map object replace with variables. Here is my code example....
So how can I achieve that
I want replace Json object with dart variable
class Data {
late String slug;
Map<String, String> singleProductVariable = {"slug": "$slug"};
}
Firstly, there is no JSON in your code sample.
I assume that you would like to set the value of the corresponding key in your Map when setting the variable.
If so, you might want to use a setter in a next way:
class Data {
String _slug;
late Map<String, String> v = {"slug": _slug};
Data(String slug) : _slug = slug;
set slug(String str) => v['slug'] = str;
}
void main() {
final d = Data("slug");
print(d.v);
d.slug = "newSlug";
print(d.v);
}
The output of the code above will be:
{slug: val}
{slug: newVal}
Related
In my flutter project, I want to use built_value for json serialization. One of the sample classes is:
import 'dart:convert';
import 'package:built_value/built_value.dart';
import 'package:built_value/serializer.dart';
part 'device.model.g.dart';
abstract class Device implements Resource, Built<Device, DeviceBuilder> {
// Fields
String get name;
String get code;
bool get isActive;
Device._();
factory Device([void Function(DeviceBuilder) updates]) = _$Device;
String toJson() {
return json.encode(serializers.serializeWith(Device.serializer, this));
}
factory Device.fromJson(String jsonString) {
return serializers.deserializeWith(
Device.serializer, json.decode(jsonString))!;
}
static Serializer<Device> get serializer => _$deviceSerializer;
}
I used the build_runner to generate the codes and everything is OK.
Also I have defined the serializers:
part 'serializers.g.dart';
final standardSerializers =
(serializers.toBuilder()..addPlugin(StandardJsonPlugin())).build();
#SerializersFor([
Device])
final Serializers serializers = _$serializers;
Now I want to use the toJson() method:
final device = Device((d) => d
..code = "DEV11"
..name = "Some Tools"
..isActive = true);
print(device.toJson());
The output is:
["name","Some Tools","code","DEV11","isActive",true]
which is a List of objects, instead of Map<String, dynamic>. The generated serializer is:
Iterable<Object?> serialize(Serializers serializers, Device object,
{FullType specifiedType = FullType.unspecified})
...
which returns an Iterable of Object?.
How can I make built_value to generate a json with the standard format, i.e:
{"name":"Some Tools","code":"DEV11","isActive":true};
P.S: using the dart encoder,
print(json.encode(device));
results in:
"[\"name\",\"Some Tools\",\"code\",\"DEV11\",\"isActive\",true]"
I made a silly mistake. Should be:
#SerializersFor([
Device,
])
final Serializers serializers =
(_$serializers.toBuilder()..addPlugin(StandardJsonPlugin())).build();
I am trying to initialise the field tasks in the below code but I am getting the error: Non-nullable instance field 'tasks' must be initialized.. I can successfully initialise fields using syntax like Example(this.tasks) {} or Example(String json) : this.tasks = [json] but I am unsure how to initialise a field when I need to use multiple lines to calculate the value like in the below code.
import 'dart:convert';
class Example {
List<String> tasks;
Example(String json) {
List<String> data = jsonDecode(json);
this.tasks = data;
}
}
In this example you don't need multiple lines to compute the value. You can just do:
Example(String json) : this.tasks = jsonDecode(json);
In the more general case where you do need multiple statements, if the field initialization values are unrelated, I'd use helper functions for each:
Example(String json) : this.tasks = _computeTasks(json);
static List<String> _computeTasks(String json) {
List<String> result;
// compute compute compute
return result;
}
If you have multiple fields that need to be initialized with values from the same computation, I'd first try to make it a factory constructor:
final Something somethingElse;
Example._(this.tasks, this.somethingElse);
factory Example(String json) {
List<String> tasks;
Something somethingElse;
// compute compute compute
return Example._(tasks, somethingElse);
}
If the constructor needs to be generative, and you need to compute multiple values in the same computation, and it's really important to not change this, then I'd probably make an intermediate object holding those values:
Example(String json) : this._(_computeValues(json));
Example._(_Intermediate values)
: tasks = values.tasks, somethingElse = values.somethingElse;
static _Intermediate _computeValues(String json) {
List<String> tasks;
Something somethingElse;
// compute compute compute
return _Intermediate(tasks, somethingElse);
}
...
}
// Helper class.
class _Intermediate {
final List<String> tasks;
final Something somethingElse;
_Intermediate(this.tasks, this.somethingElse);
}
If the types are the same, you can perhaps use a List instead of a helper class for the intermediate value. Or, you might be able to reuse a class like
class Pair<S, T> {
final S first;
final T second;
Pair(this.first, this.second);
}
It's not very important how you do it, the user will never see the intermediate value.
You are correct, non-nullable values must be initialized first upon object construction either as arguments, or in the initializer list.
You cannot however call methods on your object before initialization is complete. (And you probably shouldn't anyway as object construction should be kept as lightweight as possible)
If you have any processing that needs to be done before (or after) constructing an object, a factory constructor can be used. In fact it looks like you are trying to create an object from json which is just what is exemplified in the official docs.
To simplify that example i have linked to and remove anything about caching, it would look something like this:
class Logger {
String name;
bool mute = false;
factory Logger.fromJson(Map<String, Object> json) {
return Logger._internal(json['name'].toString());
}
Logger._internal(this.name);
}
Irn's solution is good. You could also make tasks nullable, if that's OK with you:
List<String>? tasks;
I made Hindi Vocabulary app using flutter.
I want to know how to convert a List<Map<String,String>> to a Set<Map<String,String>>.
Because if users add some words which they want to remind, they can add this in unmemory list. But if they see the same section, the words they want to add are overlapped. So I want to terminate the overlapping words using the set.
Here is my code:
class unMemory_words {
String words;
String word_class;
String mean;
String example_hindi;
String example_korean;
Map<String, String> _saved_word_list;
static List<Map<String, String>> list = new List<Map<String, String>>();
unMemory_words(
String words,
String word_class,
String mean,
String example_hindi,
String example_korean,
) {
this.words = words;
this.word_class = word_class;
this.mean = mean;
this.example_hindi = example_hindi;
this.example_korean = example_korean;
_saved_word_list = {
'hindi': this.words,
'case': this.word_class,
'meaning': this.mean,
'hindi_example_sentence': this.example_hindi,
'korean_example_sentence': this.example_korean
};
list.add(_saved_word_list);
}
}
Thank you!
You can do this by this way:
final list = <Map<String, String>>[];
final set = list.toSet();
Here is my class:
class WorldTimeClass {
String flag;
String url;
String time;
String location;
WorldTimeClass({this.flag, this.url, this.time, this.location});
Future<String> getData() async {
try{
Response load = await get('http://worldtimeapi.org/api/timezone/$url');
Map x(){if(load.statusCode == 200){
print(load.statusCode);
Map map = jsonDecode(load.body);
return map;}
else{
print('No Access');
return {1:'NoAccess.'};}
}
Map myMap = x();
String datetime = myMap['utc_datetime'];
String offsetUTC = myMap['utc_offset'];
DateTime dateTimeObjectConvert = DateTime.parse(datetime);
// Below converts the datetime string to a DateTime Object and then converts the UTC Offset to a substring only '01' out of +01:00 and then converts it to an int Object and then adds it to the DateTime Object as a Duration (hours);
dateTimeObjectConvert = dateTimeObjectConvert.add(Duration(hours: int.parse(offsetUTC.substring(1,3))));
return time = dateTimeObjectConvert.toString();
}
catch(e,s){
return 'Could not access time data from API.\nWe are sorry, please try again.\nError occured: $e';
}
}
var myString = getData().then((value) => value);
DateFormat pretty = DateFormat().add_jm().format(myString);
}
How can I access myString and execute it inside my class in order to use the resulting String object to use it inside a second method pretty ?
Also, I need to understand what does the below exception mean?
Only static members can be accessed in initializers.
Only static members can be accessed in initializers.
This basically means that you cannot call methods of a class or access properties of a specific class directly under class declaration.
You are getting the error on those two lines:
var myString = getData().then((value) => value);
DateFormat pretty = DateFormat().add_jm().format(myString);
Therefore create a method that returns a String then all you have to do is to call that method and it will give you the String, and add the code above inside the method:
String getDateFormat(){
var myString = getData().then((value) => value);
return DateFormat().add_jm().format(myString);
}
To access your myString variable you'll have to do one of those things:
Instantiate an WorldTimeClass object and access it using yourWorldClassObject.myString
Make it into in static member by using the static keyword like static var myString. This is what " Only static members can be accessed in initializers. " is all about. You have to create an instance of the class if you want to access it's properties, or make them static to access them without the need to instantiate an object. Simply WorldTimeClass.myString.
I am making a pokemon app and I have a question that I already had in other projects and I would like to know if anyone can help me with a solution.
I receive a variable called pokemonName from other screen, I want to pass the variable and concatenate with the class "Strings", it will be like Strings.+pokemonName.toLowerCase(), converting to lowercase to get the map from the class Strings, but I don't know how to achieve this to remove the switch and don't need to use a lot of cases for each pokemon.
class PokemonDetailScreen extends StatelessWidget {
final String pokemonName;
final String image;
Map<String, dynamic> pokemonMap = {};
PokemonDetailScreen(this.pokemonName, this.image, this.index){
getPokemonMap();
}
#override
Widget build(BuildContext context) {
return Container();
}
void getPokemonMap(){
switch(pokemonName){
case "Bulbasaur":
pokemonMap = Strings.bulbasaur;
break;
case "Charmander":
pokemonMap = Strings.charmander;
break;
}
}
}
**Class in another dart file:**
class Strings {
static Map bulbasaur = {};
}
What I needed is something like this:
void getPokemonMap(){
pokemonMap = Strings.$pokemonMap.toLowerCase();
}
What you could do is have a static map indexed by the name of your Pokemons and whose values are maps.
class Strings {
static Map<String, dynamic> map = {
'Bulbasor': {},
'Charmander': {},
// ...
};
}
And you’ll use it like this: pokemonMap = Strings.map[pokemonName].
~You can use JSON file to do all this things instead use a class.~
I recommend not use a static class to do that thing, instead you can just make a normal class and instantiate on another file, so when the class that you call your another class will be dispose when the parent was.
class PokemonStrings {
Map bulbasaur = {your map here};
}
To call that in another file you need just do
PokemonString _pokemonString = PokemonString();
And call whatever you need in the class that you instantiate
var bulbasaurMap = _pokemonString.bulbasaur;
But even so you need walk with static class. Just call the name of class followed by dot to access all the static attributes
var bulbasaurMap = PokemonString.bulbasaur;