0

How would one go about decoding a JSON String that looks like this and turn it into a Expansion Tile List with the dropdown of each tile being the "ownerhistory" of each tile:

[
  {
    "bookName": "Harry Potter",
    "Ownerhistory": [
      {
        "name": "Jane",
        "address": "USA",
      },
      {
        "name": "Dan",
        "address": "Russia",
      }
    ]
  },
  {
    "bookName": "Harry Potter",
    "Ownerhistory": [
      {
        "name": "Mary",
        "address": "USA",
      },
      {
        "name": "Ann",
        "address": "Mexico",
      },
      {
        "name": "Molly",
        "address": "Canada",
      }
    ]
  }
]

I pretty much have an idea how to display it, but i could not test it as of the moment since im having a hard time converting the json into a list that i can use to create the widgets

class BookScreen extends ConsumerWidget {
  const BookScreen({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    
    //JSON Arrives here, i already tested this code and confirms that
    //i am recieving the JSON String
    final jsonStringData = ref.watch(responseProvider); //JSON arrives here
    var tagsJson = jsonDecode(jsonStringData);
    //Attempt at converting but throws an error and i have no clue what its doing
    List<dynamic> tags = tagsJson != null ? List.from(tagsJson) : null; 

    return Column(
      children: <Widget>[
        for ( var i in bookList ){ //not currently sure if this is done properly to iterate through the list
          ExpansionTile(
            title: const Text(i.bookName),
            chrildren: <Widgets>[
              for ( var j in i.OwnerHistory)
                ListTile(title: Text(j));;
            ]
          );
        }
      ],
    );
  }
}

2 Answers 2

0

Try the code below (you can copy & paste to dartpad.dev). But please note that the JSON string in your question is not valid. You need to remove the commas from the lines which are the last in a block, for example "address": "USA", should be "address": "USA". (I did this to test my answer).

import 'package:flutter/material.dart';
import 'dart:convert';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
        debugShowCheckedModeBanner: false, home: Scaffold(body: BookScreen()));
  }
}

class BookScreen extends StatelessWidget {
  const BookScreen({super.key});

  @override
  Widget build(BuildContext context) {
    final jsonStringData =
        '[{"bookName":"HarryPotter","Ownerhistory":[{"name":"Jane","address":"USA"},{"name":"Dan","address":"Russia"}]},{"bookName":"HarryPotter","Ownerhistory":[{"name":"Mary","address":"USA"},{"name":"Ann","address":"Mexico"},{"name":"Molly","address":"Canada"}]}]';

    final json = jsonDecode(jsonStringData);

    List<Map<String, dynamic>> books = json != null ? List.from(json) : [];

    return Column(
        children: books
            .map((book) => ExpansionTile(
                title: Text(book['bookName']),
                children: book['Ownerhistory']
                    .map<Widget>((owner) => ListTile(
                        title: Text(owner['name']),
                        subtitle: Text(owner['address'])))
                    .toList()))
            .toList());
  }
}
Sign up to request clarification or add additional context in comments.

Comments

0

I don't prefer doing serialization & deserialization here , you create another dart file and defining the mechanism for JSON handling , in your case will be:

 import 'dart:convert';

List<LibModel> libModelFromJson(String str) => List<LibModel>.from(json.decode(str).map((x) => LibModel.fromJson(x)));

String libModelToJson(List<LibModel> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));

class LibModel {
    final String bookName;
    final List<Ownerhistory> ownerhistory;

    LibModel({
        required this.bookName,
        required this.ownerhistory,
    });

    factory LibModel.fromJson(Map<String, dynamic> json) => LibModel(
        bookName: json["bookName"],
        ownerhistory: List<Ownerhistory>.from(json["Ownerhistory"].map((x) => Ownerhistory.fromJson(x))),
    );

    Map<String, dynamic> toJson() => {
        "bookName": bookName,
        "Ownerhistory": List<dynamic>.from(ownerhistory.map((x) => x.toJson())),
    };
}

class Ownerhistory {
    final String name;
    final String address;

    Ownerhistory({
        required this.name,
        required this.address,
    });

    factory Ownerhistory.fromJson(Map<String, dynamic> json) => Ownerhistory(
        name: json["name"],
        address: json["address"],
    );

    Map<String, dynamic> toJson() => {
        "name": name,
        "address": address,
    };
}

Now you have a list of objects and you can directly use it in your app, guess it would be:

List<LibModel> yourListVar = libModelFromJson(jsonStringData);

then use the var yourListVar directly when ever and however you want

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.