Home > Software design >  How do i get json data and then place it inside another variable without having to worry about Futur
How do i get json data and then place it inside another variable without having to worry about Futur

Time:04-17

In my use case i have to change the layout of the app with json data. I have a json file which i want to get and use the key values without using Future method in the next method rather i want to place the mapped json and place it in an empty curly brackets:

This is the json file i grab:

# test_json.json

{
"fontSize" : "10",
"fontFamily" : "A",
"fontWeigth" : "bold",
"fontColor" : "blue"
}

This is the file which grabs the json file and maps it:

# get_json.dart


class GetJson{
  Future<Map<String, dynamic>> getJson() async {
    String jsonData =
        await rootBundle.loadString('assets/json/test_json.json');
    Map<String, dynamic> data = jsonDecode(jsonData);
    return data;
  }


}

Then i grab this mapped json and i want to place it inside a variable called mappedData and place it inisde empty curly brackets. Then i want to get the number with getNumber() and inisde this method i convert the type of fontSize from string to double with another custom method called TypeConvertor.getDouble():

class Utility {
  var mappedData= {};

 setJson() async {
    mappedData = await GetJson().getJson();
  }

getNumber(String key) {
    var data = mappedData;
    return TypeConvertor.getDouble(data[key]);
  }
}

In my use case i need to this like this i have no other choice. I want to explicitly grab the json like that and i don't want getNumber() to be a Future because then i cannot place Utility().getNumber("fontSize") inside a stateful widget because then i have to use setState and i want to avoid that because i will have alot of keys beside fontSize and so then i have to use setState for every key values. I just want to use Utility().getNumber("fontSize") inside property fontSize and The rest also like this. In my usecase i have to do it like that:



class TestView extends StatefulWidget {
  const TestView({Key? key}) : super(key: key);

  @override
  State<TestView> createState() => _TestViewState();
}

class _TestViewState extends State<TestView> {
  @override
  Widget build(BuildContext context) {
    return Text(
      "test",
      style: TextStyle(fontSize: Utility().getNumber("fontSize")),
    );
  }
}


But in my app mappedData gives null. The full error is : Unhandled Exception: type 'Null' is not a subtype of type 'String' and the null value is inside mappedData. I want to grab the json data and place it inside an empty map and use the mapped json from there on. How do i resolve the null execption issue?

EDIT

Change variables to correct versions

CodePudding user response:

Probably it's because you don't call setJson before call getNumber. The following code is work.

final utility = Utility();
await utility.setJson();
print(utility.getNumber("fontSize"));

If you want to avoid similar mistakes, you have some options as solutions.

  • Include mappedData to Utility's constructor.
  • Change getNumber to static, and add argument mappedData.
  • Use JsonSerializable(It's a little difficult but the best solution.)

CodePudding user response:

I found the solution which is partly contributed by @bakatsuyuki. So i did use await utility.setJson(); but i also initilized it with initState() so field utility has no null value. I also used FutureBuilder() to check if snapshot.hasData and then i display the Text() widget with the data from utilitiy else show empty Container. This way i can resolve the null Exception.

This is the view that worked for me:



class AppView extends StatefulWidget {
  const AppView({
    Key? key,
  }) : super(key: key);

  @override
  _AppViewState createState() => _AppViewState();
}

class _AppViewState extends State<AppView> {
  final utility = Utility();

  Future setUtility() async {
    await utility.setJson();
  }

  @override
  void initState() {
    setUtility();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: FutureBuilder(
            future: AppContent().getAppContent(),
            builder: (context, snapshot) {
              if (snapshot.hasData) {
                return Text("test",
                    style: TextStyle(
                      fontSize: utility.getNumber("fontSize"),
                    ));
              } else {
                return Container();
              }
            }),
      ),
    );
  }
}

  • Related