4

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!

alvarlagerlof
  • 1,516
  • 1
  • 18
  • 27

2 Answers2

3

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;
  }
diegoveloper
  • 93,875
  • 20
  • 236
  • 194
  • I cannot do it manually like that, will be lots data. But thanks for the decoding! – alvarlagerlof Dec 08 '18 at 17:19
  • what do you mean? the only thing you can do in a loop is this var: data["app_tabs"] <-- you will have to iterate, because it's an array, in my answer I was just using the first item [0] to show you how to decode, because that was your question – diegoveloper Dec 08 '18 at 17:21
  • No, I want to iterate over the whole map. This json is not final, and manual loops will not be a good solution. – alvarlagerlof Dec 08 '18 at 17:42
  • you have to extract each value of the map, you can iterate the 'app_tabs' array because 'it's an array' , after you extract each value of the map, you have to decode each value because it's on base64, your map is not in base64, but each value is. :) do you understand? – diegoveloper Dec 08 '18 at 17:43
  • You don't seem to understand what I am saying. It needs to be automatic. The text "app-tabs" cannot be in the code. I need it to be recrusive. – alvarlagerlof Dec 08 '18 at 18:12
  • That's possible but it is not what we don't normally do. You should expect a json with fixed names. The only thing that change is the data inside the fields. I suggest you to update your answer and specify that you need automatic parser. – diegoveloper Dec 08 '18 at 18:17
2

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));
}
alvarlagerlof
  • 1,516
  • 1
  • 18
  • 27