Home > Software engineering >  How can I map a JSON map to single key multiple values
How can I map a JSON map to single key multiple values

Time:10-26

This might be a bit of broad question.

I have an JSON Map Array which i can parse normally. But i would like to MAP multiple Values to a Single key. I am stuck and unsure how to proceed.

My JSON output. I cannot change this.

    {
    "pos":"1",
    "element":"37542",
    "title":"Easy On Me",
    "inter":"Adele",
    "isnew":"0"
    },
    {
    "pos":"66",
    "element":"37183",
    "title":"Send My Love",
    "inter":"Adele",
    "isnew":"0"
    }

this is just a snippet of the actual JSON objects

what I would like to do is something like Map<String,List<String,String>>

Adele

  • Easy On Me, 37542
  • Send My Love, 37183

Searching online I find a lot of examples how to parse JSON normally, but never found a version where you can iterate through a JSON version like above and pull parts of the map out and add it to another.

any help would be appreciated. Thank you in advance

import 'dart:convert';
import 'package:http/http.dart' as http;
import 'dart:async';

class SongList {
  final List<Song> songs;

  SongList({
    required this.songs,
  });

  factory SongList.fromJson(List<dynamic> parsedJson) {
    List<Song> songs = <Song>[];
    songs = parsedJson.map((i) => Song.fromJson(i)).toList();

    return SongList(songs: songs);
  }
}

class Song {
  final String? pos;
  final String? element;
  final String? title;
  final String? inter;
  final String? isnew;

  const Song(
      {required this.pos,
      required this.element,
      required this.title,
      required this.inter,
      required this.isnew});

  factory Song.fromJson(Map<String, dynamic> data) {
    return Song(
      pos: data['pos'] as String?,
      element: data['element'] as String?,
      title: data['title'] as String?,
      inter: data['inter'] as String?,
      isnew: data['isnew'] as String?,
    );
  }
}

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

class Songs extends StatefulWidget {
  final String pos;
  final String element;
  final String title;
  final String inter;
  final String isnew;

  const Songs(
      {super.key,
      required this.pos,
      required this.element,
      required this.title,
      required this.inter,
      required this.isnew});

  @override
  State<Songs> createState() => _SongsState();
}

class _SongsState extends State<Songs> {
  late AudioPlayer player;

  @override
  void initState() {
    super.initState();
    player = AudioPlayer();
  }

  @override
  void dispose() {
    player.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    var titles = Row(
      mainAxisSize: MainAxisSize.min,
      children: [
        Column(children: [
          SizedBox(
            height: 25,
            width: 200,
            child: Text(
              widget.title,
              style: const TextStyle(fontSize: 14),
              textAlign: TextAlign.center,
            ),
          ),
          SizedBox(
            height: 25,
            width: 200,
            child: Text(
              widget.inter,
              style: const TextStyle(fontSize: 10),
              textAlign: TextAlign.center,
            ),
          ),
        ]),
      ],
    );
    return FittedBox(
        fit: BoxFit.contain,
        child: Card(
            child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            Column(
              children: [
                Center(
                    child: SizedBox(
                        height: 50,
                        width: 50,
                        child: Align(
                            alignment: Alignment.center,
                            child: widget.isnew != "1"
                                ? Text(
                                    widget.pos.toString(),
                                    textAlign: TextAlign.center,
                                  )
                                : const Text(
                                    "new",
                                    textAlign: TextAlign.center,
                                    style: TextStyle(color: Colors.red),
                                  )))),
              ],
            ),
            Column(
              children: [
                SizedBox(
                  height: 50,
                  width: 50,
                  child: Image.network(
                      '${'http://www.example.com/${widget.element}'}.jpg'),
                ),
              ],
            ),
            Column(
              children: [
                titles,
              ],
            ),
            Column(
              children: [
                SizedBox(
                  height: 50,
                  width: 50,
                  child: TextButton(
                    onPressed: () async {
                      final url =
                          '${'http://www.example.com/${widget.element}'}.mp3';
                      await player.setUrl(url);
                      player.play();
                    },
                    child: Image.asset('assets/images/btn_play.png'),
                  ),
                ),
              ],
            ),
            Column(
              children: [
                SizedBox(
                  height: 50,
                  width: 50,
                  child: TextButton(
                    // ignore: avoid_print
                    onPressed: () =>
                        print('pressed button download!! ${widget.element}'),
                    child: Image.asset('assets/images/btn_download.png'),
                  ),
                ),
              ],
            ),
          ],
        )));
  }
}


Future<SongList> fetchSong() async {
  final response = await http
      .get(Uri.parse('http://example.com'));
  if (response.statusCode == 200) {
    return SongList.fromJson(jsonDecode(response.body));
  } else {
    throw Exception('Failed to Load Songs');
  }
}

//snippet from class that instatiates
  late Future<SongList> futureSong;

  @override
  void initState() {
    super.initState();
    futureSong = fetchSong();
  }

//snippet from class that builds the list
FutureBuilder<SongList>(
          future: futureSong,
          builder: (context, AsyncSnapshot<SongList> snapshot) {
            if (snapshot.hasData) {
              return ListView.builder(
                  itemCount: snapshot.data!.songs.length,
                  itemBuilder: (context, index) {
                    if (snapshot.data!.songs[index].element.toString() !=
                        "null") {
                      return Songs(
                          element:
                              snapshot.data!.songs[index].element.toString(),
                          inter: snapshot.data!.songs[index].inter.toString(),
                          isnew: snapshot.data!.songs[index].isnew.toString(),
                          pos: snapshot.data!.songs[index].pos.toString(),
                          title: snapshot.data!.songs[index].title.toString());
                    } else {
                      return const SizedBox(height: 0);
                    }
                  });
            } else if (snapshot.hasError) {
              return Text('${snapshot.error}');
            }

            // By default, show a loading spinner.
            return const CircularProgressIndicator();
          }

CodePudding user response:

This might work:

void main() {
  var data=[
    {
    "pos":"1",
    "element":"37542",
    "title":"Easy On Me",
    "inter":"Adele",
    "isnew":"0"
    },
    {
    "pos":"66",
    "element":"37183",
    "title":"Send My Love",
    "inter":"Adele",
    "isnew":"0"
    },
    {
    "pos":"80",
    "element":"5000",
    "title":"Enjoy the silence",
    "inter":"Depeche Mode",
    "isnew":"0"
    },
    {
    "pos":"100",
    "element":"6000",
    "title":"In your room",
    "inter":"Depeche Mode",
    "isnew":"0"
    }
  ];

  var result = <String,List<Map<String,String>>>{};
  for (var d in data) {
    print(d);
    var e={"element":d["element"]!, "title": d["title"]!};
    var key=d["inter"]!;
    if (result.containsKey(key)) {
      result[key]!.add(e);
    } else {
      result[key]=[e];
    }
  }
  print(result);
  
}

CodePudding user response:

You can achieve this by creating a subclass.

Interpret interpretFromJson(String st) => Interpret.fromJson(json.decode(st));

class Interpret{
  Interpret({
    required this.name,
    required this.titles,
  });

  final String name;
  final List<Title> titles;

  factory Interpret.fromJson(Map<String, dynamic> json) => Title(
        name: json["inter"],
        titles: List<Title>.from(json.map((x) => Title.fromJson(x))),
      );
}

class Title {
  Title({
    required this.name,
    required this.element,
  });

  final String name;
  final double element;

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

Then you can just call it like.

InterpretFromJson(json);
  • Related