'Parsing Nested JSON within Flutter

I am trying to parse nested JSON from the VirusTotal API but when ran it comes back as this error, I tried a different method found in https://app.quicktype.io/ but it came back as NULL and I couldn't get that working either

 Unhandled Exception: type '_InternalLinkedHashMa
p<String, dynamic>' is not a subtype of type 'Data'

My code is below, I am parsing 2 APIs and one is working so ignore the other one, if possible I would like to do this without completely rewriting my program as time is thin.

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:sms/sms.dart';
import 'package:http/http.dart' as http;

String url = "https://urlhaus-api.abuse.ch/v1/urls/recent/"; //address for URL file




Future<void> main() async {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key:key);
  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: "Gone Smishin'",
      home:  GoneSmishin(),
    );
  }
}

class GoneSmishin extends StatefulWidget {
  const GoneSmishin({Key? key}) : super(key: key);
  State<GoneSmishin> createState() {
    return _GoneSmishinState();
  }
}

class Data {
  late Attributes attributes;

  Map<String, dynamic> toJson() => {
    "attributes": attributes.toJson(),
  };
}
class Attributes {
  late LastAnalysisStats lastAnalysisStats;

  Map<String, dynamic> toJson() => {
    "last_analysis_stats": lastAnalysisStats.toJson(),
  };
}
class LastAnalysisStats {
  static late int malicious;
  static late int suspicious;

  Map<String, dynamic> toJson() => {
    "malicious": malicious,
    "suspicious": suspicious,
  };
}


class _GoneSmishinState extends State<GoneSmishin> {

  late Data data;

  String message = "";
  String word = "";
  bool isOn = false;

  final myController = TextEditingController();


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

  var attributes = '';

  String urlHaus = "URLHaus";
  String virusTotal = "VirusTotal";
  String list = "Whitelist";


  urlHausParseBox() async {
    String url = myController.text;
    var urlEncoded = base64.encode(utf8.encode(myController.text));
    var urlNoPadding = urlEncoded.replaceAll(new RegExp(r'='), '');

    final response2 = await http.get(
      Uri.parse("https://www.virustotal.com/api/v3/urls/$urlNoPadding"),
      headers: <String, String>{
        'Accept': 'application/json',
        'x-apikey': '11111111111111111111111111111111111111'
      },
    );

    print(urlEncoded);
    print(response2.body);
    if (response2.statusCode == 200) {
      setState(() {
        final decoded = json.decode(response2.body);
        data = decoded['data'];
      });
    }
    if (((LastAnalysisStats.suspicious) + (LastAnalysisStats.malicious)) >= 2) {
      setState(() {
        virusTotal = 'Found in VirusTotal - Possibly Malicious';
      });
    } else if (((LastAnalysisStats.suspicious) + (LastAnalysisStats.malicious)) <= 1) {
      setState(() {
        virusTotal = 'Found in VirusTotal - Probably not Malicious';
        print((LastAnalysisStats.suspicious) + (LastAnalysisStats.malicious));
      });
    } else {
      setState(() {
        virusTotal = 'Not found in VirusTotal';
      });


Solution 1:[1]

import 'dart:convert';

import 'package:wnetworking/wnetworking.dart';

class VirusTotal {
  final _url = 'https://www.virustotal.com/api/v3/urls';
  final apiKey = '1111111111111111111111111111111111111111';
  /* ---------------------------------------------------------------------------- */
  Future<void> getUrlAnalysisReport(String url) async {
    var urlEncoded = base64.encode(utf8.encode(url));
    var urlId = urlEncoded.replaceAll(RegExp(r'='), '');
    var response = await HttpReqService.get<JMap>(
      '$_url/$urlId', 
      jsonResponse: true,
      auth: AuthType.apiKey,
      authData: MapEntry('x-apikey', apiKey),
    );
    
    print(response?['data']['attributes'].keys.toList());
  }
}

void main(List<String> args) async {
  await VirusTotal().getUrlAnalysisReport('https://www.edx.org');
  print('\nJob done!');
}

Output:

[last_modification_date, last_http_response_cookies, times_submitted, total_votes, title, last_submission_date, last_http_response_content_length, last_http_response_headers, reputation, threat_names, tags, last_analysis_date, first_submission_date, categories, last_http_response_content_sha256, last_http_response_code, last_final_url, trackers, url, last_analysis_stats, last_analysis_results, html_meta, outgoing_links]

Job done!

You need to create your classes according to 'attributes' map, you can use this tool.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1