I have json where each value is encoded as base64. I want to go trough the whole tree and decode every value. This needs to be automatic. No json key can be specified in the code. It needs to go down itself. How would i go about that?

This is what I have so far

Map<String, dynamic> parseJson(String response) {
  var data = json.decode(response);

  // Here I need to decode from base64

  return data;
}

This is what the json looks like

{
   "app_title":"RnJpU8Okaw==",
   "app_color":"I0ZGRUUzMw==",
   "app_tabs":[
      {
         "title":"RW4gdGl0ZWwgw6XDpMO2w4XDhMOW",
         "content":"CkxpdGUgaW5uZWjDpWxsLiA8YnIgLz4gCjxiPmhlajwvYj4gCjxoMT50ZXN0PC9oMT4KPGEgaHJlZj0iaHR0cDovL2ZyaXNrb2xhLm51Ij5FbiBsw6RuazwvYT4KPGRpdiBzdHlsZT0iY29sb3I6IGdyZWVuIj5MaXRlIGdyw7ZuIHRleHQga2Fuc2tlPzwvZGl2Pgo8aW1nIHNyYz0iaHR0cDovL2ZyaXNrb2xhLm51L2ltYWdlcy9zb2ZyaV9sb2dvdHlwLnBuZyIgLz4K"
      },
      {
         "title":"RW4gdGl0ZWwgw6XDpMO2w4XDhMOW",
         "content":"CkxpdGUgaW5uZWjDpWxsLiA8YnIgLz4gCjxiPmhlajwvYj4gCjxoMT50ZXN0PC9oMT4KPGEgaHJlZj0iaHR0cDovL2ZyaXNrb2xhLm51Ij5FbiBsw6RuazwvYT4KPGRpdiBzdHlsZT0iY29sb3I6IGdyZWVuIj5MaXRlIGdyw7ZuIHRleHQga2Fuc2tlPzwvZGl2Pgo8aW1nIHNyYz0iaHR0cDovL2ZyaXNrb2xhLm51L2ltYWdlcy9zb2ZyaV9sb2dvdHlwLnBuZyIgLz4K"
      },
      {
         "title":"RW4gdGl0ZWwgw6XDpMO2w4XDhMOW",
         "content":"CkxpdGUgaW5uZWjDpWxsLiA8YnIgLz4gCjxiPmhlajwvYj4gCjxoMT50ZXN0PC9oMT4KPGEgaHJlZj0iaHR0cDovL2ZyaXNrb2xhLm51Ij5FbiBsw6RuazwvYT4KPGRpdiBzdHlsZT0iY29sb3I6IGdyZWVuIj5MaXRlIGdyw7ZuIHRleHQga2Fuc2tlPzwvZGl2Pgo8aW1nIHNyYz0iaHR0cDovL2ZyaXNrb2xhLm51L2ltYWdlcy9zb2ZyaV9sb2dvdHlwLnBuZyIgLz4K"
      }
   ]
}

Thanks!


Solution 1: diegoveloper

This is how you can do it, using Base64Codec , if you use utf8.decode you won't lose the encoding.

  import 'dart:convert';

  Base64Codec base64 = const Base64Codec();
Map<String, dynamic> parseJson(String response) {
    final data = json.decode(response);

    // Here I need to decode from base64
    final dataTitle = data["app_title"];
    final dataColor = data["app_color"];

    //decode base64
    final dataTitle64 = base64.decode(dataTitle);
    final dataColor64 = base64.decode(dataColor);

    //Strings
    String stringTitle = utf8.decode(dataTitle64);
    String stringColor = utf8.decode(dataColor64);

    //content array
    List<Item> list = List();
    for (Map<String, dynamic> value in data["app_tabs"]){
       final mapTitle = base64.decode(value["title"]);
       final mapContent = base64.decode(value["content"]);
       String stringTitle = utf8.decode(mapTitle);
       String stringContent = utf8.decode(mapContent);
       list.add(Item(stringTitle, stringContent));
    }

    //now you have your list of items

    for(Item item in list){
       print("ITEM: ${item.title} .. ${item.content}");
    }
    //return that list if you want

    return data;
  }


Solution 2: alvarlagerlof

I ended up solving it myself! This is the final code:

import 'dart:async';
import 'dart:convert';

import 'package:flutter/foundation.dart';
import 'package:http/http.dart' as http;

Future<Map<String, dynamic>> fetchJson() async {
  final res = await http.get('http://app.roboro.se/json/001');

  if (res.statusCode == 200) {
    return compute(parseJson, res.body);
  } else {
    throw Exception('Failed to load json');
  }
}

Map<String, dynamic> parseJson(String response) {    
  return walkJson(json.decode(response));
}

Map<String, dynamic> walkJson(data) {
  data.forEach((key, value) {
    if (value is List == false) {
      data[key] = base64Decode(value);  
    } else {
      value.forEach((item) => item = walkJson(item));
    }
  });

  return data;
}

String base64Decode(String encoded) {
  return utf8.decode(base64.decode(encoded));
}