如何在Flutter中解析嵌套的JSON

时间:2019-11-18 18:38:27

标签: json flutter

我在解析JSON时遇到问题,想要一些帮助。

这是我的JSON的摘要

"geocoded_waypoints":[  ],
   "routes":[ 
      { 
         "bounds":{  },
         "copyrights":"Map data ©2019 Google",
         "legs":[ 
            { 
               "arrival_time":{  },
               "departure_time":{  },
               "distance":{  },
               "duration":{  },
               "end_address":"dsfsfsdf32434324",
               "end_location":{  },
               "start_address":"123123123123adsfdsfsdfsd",
               "start_location":{  },
               "steps":[ 
                  { 
                     "distance":{  },
                     "duration":{  },
                     "end_location":{  },
                     "html_instructions":"Walk to abc",
                     "polyline":{  },
                     "start_location":{ 
                        "lat":1232131,
                        "lng":11231
                     },
                     "steps":[ 
                        { 
                           "distance":{ 
                              "text":"55 m",
                              "value":55
                           },
                           "duration":{ 
                              "text":"1 min",
                              "value":52
                           },
                           "end_location":{ 
                              "lat":1.3775668,
                              "lng":103.8481395
                           },
                           "html_instructions":"Head \u003cb\u003ewest\u003c/b\u003e toward \u003cb\u003e123 abc Kio Ave G\u003c/b\u003e",
                           "polyline":{ 
                              "points":"galGu|yxRH|@BZ"
                           },
                           "start_location":{ 
                              "lat":122,
                              "lng":1231
                           },
                           "travel_mode":"WALKING"
                        },

这是我当前的代码解析JSON对象的方式

class Steps {
  final String routes;
  final String legs;
  final String steps;
  final Route html_instructions;

  Steps({this.routes, this.legs, this.steps, this.html_instructions});

  factory Steps.fromJson(Map<String, dynamic> json) {
    return Steps(
      routes: json['routes'],
      legs: json['legs'],
      steps: json['steps'],
      html_instructions: Route.fromJson(json['html_instructions'])
    );
  }

  static List<String> parseRoute(routesJson){
    List<String> routeList = new List<String>.from(routesJson);
    return routeList;
  }
}

class Instructions {
  final String route;

  Instructions({this.route});

  factory Instructions.fromJson(Map<String, dynamic> json) {
    return Instructions(route: json['html_instructions']);
  }
}

class Route {
  final String stepp;
  final Instructions instructions;
  Route({this.stepp, this.instructions});

  factory Route.fromJson(Map<String, dynamic> json) {
    return Route(
      stepp: json['html_instructions'] as String,
      instructions: Instructions.fromJson(json['steps'])

    );
  }

}

我想要实现的是让我自己的html_instructions显示在我的应用程序上。我从http://www.coderzheaven.com/2019/02/19/complex-json-parsing-in-flutter-dart/开始尝试,但是无法解析,而且得到了:未处理的异常:类型'List'不是'String'类型的子类型

我期待着你们的启发,谢谢大家,祝你有美好的一天

1 个答案:

答案 0 :(得分:0)

您可以在下面复制粘贴运行完整代码
代码段

Payload payload = payloadFromJson(jsonString);
print( ' ${payload.routes[0].legs[0].steps[0].distance.text}' );
print( ' ${payload.routes[0].legs[0].steps[0].steps[0].distance.text}' );

假设您的json字符串为

{
"geocoded_waypoints":[  ],
   "routes":[ 
      { 
         "bounds":{  },
         "copyrights":"Map data ©2019 Google",
         "legs":[ 
            { 
               "arrival_time":{  },
               "departure_time":{  },
               "distance":{  },
               "duration":{  },
               "end_address":"dsfsfsdf32434324",
               "end_location":{  },
               "start_address":"123123123123adsfdsfsdfsd",
               "start_location":{  },
               "steps":[ 
                  { 
                     "distance":{ 
                              "text":"55 m",
                              "value":55
                           },
                           "duration":{ 
                              "text":"1 min",
                              "value":52
                           },
                           "end_location":{ 
                              "lat":1.3775668,
                              "lng":103.8481395
                           },
                           "html_instructions":"Head" ,
                           "polyline":{ 
                              "points":"galGu|yxRH|@BZ"
                           },
                           "start_location":{ 
                              "lat":122,
                              "lng":1231
                           },
                           "travel_mode":"WALKING",
                     "steps":[ 
                        { 
                           "distance":{ 
                              "text":"55 m",
                              "value":55
                           },
                           "duration":{ 
                              "text":"1 min",
                              "value":52
                           },
                           "end_location":{ 
                              "lat":1.3775668,
                              "lng":103.8481395
                           },
                           "html_instructions":"Head" ,
                           "polyline":{ 
                              "points":"galGu|yxRH|@BZ"
                           },
                           "start_location":{ 
                              "lat":122,
                              "lng":1231
                           },
                           "travel_mode":"WALKING"
                        }
                        ]
                        }]
                        }]
                        }]
                        }

相关的解析类为

// To parse this JSON data, do
//
//     final payload = payloadFromJson(jsonString);

import 'dart:convert';

Payload payloadFromJson(String str) => Payload.fromJson(json.decode(str));

String payloadToJson(Payload data) => json.encode(data.toJson());

class Payload {
    List<dynamic> geocodedWaypoints;
    List<Route> routes;

    Payload({
        this.geocodedWaypoints,
        this.routes,
    });

    factory Payload.fromJson(Map<String, dynamic> json) => Payload(
        geocodedWaypoints: List<dynamic>.from(json["geocoded_waypoints"].map((x) => x)),
        routes: List<Route>.from(json["routes"].map((x) => Route.fromJson(x))),
    );

    Map<String, dynamic> toJson() => {
        "geocoded_waypoints": List<dynamic>.from(geocodedWaypoints.map((x) => x)),
        "routes": List<dynamic>.from(routes.map((x) => x.toJson())),
    };
}

class Route {
    Bounds bounds;
    String copyrights;
    List<Leg> legs;

    Route({
        this.bounds,
        this.copyrights,
        this.legs,
    });

    factory Route.fromJson(Map<String, dynamic> json) => Route(
        bounds: Bounds.fromJson(json["bounds"]),
        copyrights: json["copyrights"],
        legs: List<Leg>.from(json["legs"].map((x) => Leg.fromJson(x))),
    );

    Map<String, dynamic> toJson() => {
        "bounds": bounds.toJson(),
        "copyrights": copyrights,
        "legs": List<dynamic>.from(legs.map((x) => x.toJson())),
    };
}

class Bounds {
    Bounds();

    factory Bounds.fromJson(Map<String, dynamic> json) => Bounds(
    );

    Map<String, dynamic> toJson() => {
    };
}

class Leg {
    Bounds arrivalTime;
    Bounds departureTime;
    Bounds distance;
    Bounds duration;
    String endAddress;
    Bounds endLocation;
    String startAddress;
    Bounds startLocation;
    List<Step> steps;

    Leg({
        this.arrivalTime,
        this.departureTime,
        this.distance,
        this.duration,
        this.endAddress,
        this.endLocation,
        this.startAddress,
        this.startLocation,
        this.steps,
    });

    factory Leg.fromJson(Map<String, dynamic> json) => Leg(
        arrivalTime: Bounds.fromJson(json["arrival_time"]),
        departureTime: Bounds.fromJson(json["departure_time"]),
        distance: Bounds.fromJson(json["distance"]),
        duration: Bounds.fromJson(json["duration"]),
        endAddress: json["end_address"],
        endLocation: Bounds.fromJson(json["end_location"]),
        startAddress: json["start_address"],
        startLocation: Bounds.fromJson(json["start_location"]),
        steps: List<Step>.from(json["steps"].map((x) => Step.fromJson(x))),
    );

    Map<String, dynamic> toJson() => {
        "arrival_time": arrivalTime.toJson(),
        "departure_time": departureTime.toJson(),
        "distance": distance.toJson(),
        "duration": duration.toJson(),
        "end_address": endAddress,
        "end_location": endLocation.toJson(),
        "start_address": startAddress,
        "start_location": startLocation.toJson(),
        "steps": List<dynamic>.from(steps.map((x) => x.toJson())),
    };
}

class Step {
    Distance distance;
    Distance duration;
    Location endLocation;
    String htmlInstructions;
    Polyline polyline;
    Location startLocation;
    String travelMode;
    List<Step> steps;

    Step({
        this.distance,
        this.duration,
        this.endLocation,
        this.htmlInstructions,
        this.polyline,
        this.startLocation,
        this.travelMode,
        this.steps,
    });

    factory Step.fromJson(Map<String, dynamic> json) => Step(
        distance: Distance.fromJson(json["distance"]),
        duration: Distance.fromJson(json["duration"]),
        endLocation: Location.fromJson(json["end_location"]),
        htmlInstructions: json["html_instructions"],
        polyline: Polyline.fromJson(json["polyline"]),
        startLocation: Location.fromJson(json["start_location"]),
        travelMode: json["travel_mode"],
        steps: json["steps"] == null ? null : List<Step>.from(json["steps"].map((x) => Step.fromJson(x))),
    );

    Map<String, dynamic> toJson() => {
        "distance": distance.toJson(),
        "duration": duration.toJson(),
        "end_location": endLocation.toJson(),
        "html_instructions": htmlInstructions,
        "polyline": polyline.toJson(),
        "start_location": startLocation.toJson(),
        "travel_mode": travelMode,
        "steps": steps == null ? null : List<dynamic>.from(steps.map((x) => x.toJson())),
    };
}

class Distance {
    String text;
    int value;

    Distance({
        this.text,
        this.value,
    });

    factory Distance.fromJson(Map<String, dynamic> json) => Distance(
        text: json["text"],
        value: json["value"],
    );

    Map<String, dynamic> toJson() => {
        "text": text,
        "value": value,
    };
}

class Location {
    double lat;
    double lng;

    Location({
        this.lat,
        this.lng,
    });

    factory Location.fromJson(Map<String, dynamic> json) => Location(
        lat: json["lat"].toDouble(),
        lng: json["lng"].toDouble(),
    );

    Map<String, dynamic> toJson() => {
        "lat": lat,
        "lng": lng,
    };
}

class Polyline {
    String points;

    Polyline({
        this.points,
    });

    factory Polyline.fromJson(Map<String, dynamic> json) => Polyline(
        points: json["points"],
    );

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

完整代码

import 'package:flutter/material.dart';
// To parse this JSON data, do
//
//     final payload = payloadFromJson(jsonString);

import 'dart:convert';

Payload payloadFromJson(String str) => Payload.fromJson(json.decode(str));

String payloadToJson(Payload data) => json.encode(data.toJson());

class Payload {
  List<dynamic> geocodedWaypoints;
  List<Route> routes;

  Payload({
    this.geocodedWaypoints,
    this.routes,
  });

  factory Payload.fromJson(Map<String, dynamic> json) => Payload(
    geocodedWaypoints: List<dynamic>.from(json["geocoded_waypoints"].map((x) => x)),
    routes: List<Route>.from(json["routes"].map((x) => Route.fromJson(x))),
  );

  Map<String, dynamic> toJson() => {
    "geocoded_waypoints": List<dynamic>.from(geocodedWaypoints.map((x) => x)),
    "routes": List<dynamic>.from(routes.map((x) => x.toJson())),
  };
}

class Route {
  Bounds bounds;
  String copyrights;
  List<Leg> legs;

  Route({
    this.bounds,
    this.copyrights,
    this.legs,
  });

  factory Route.fromJson(Map<String, dynamic> json) => Route(
    bounds: Bounds.fromJson(json["bounds"]),
    copyrights: json["copyrights"],
    legs: List<Leg>.from(json["legs"].map((x) => Leg.fromJson(x))),
  );

  Map<String, dynamic> toJson() => {
    "bounds": bounds.toJson(),
    "copyrights": copyrights,
    "legs": List<dynamic>.from(legs.map((x) => x.toJson())),
  };
}

class Bounds {
  Bounds();

  factory Bounds.fromJson(Map<String, dynamic> json) => Bounds(
  );

  Map<String, dynamic> toJson() => {
  };
}

class Leg {
  Bounds arrivalTime;
  Bounds departureTime;
  Bounds distance;
  Bounds duration;
  String endAddress;
  Bounds endLocation;
  String startAddress;
  Bounds startLocation;
  List<Step> steps;

  Leg({
    this.arrivalTime,
    this.departureTime,
    this.distance,
    this.duration,
    this.endAddress,
    this.endLocation,
    this.startAddress,
    this.startLocation,
    this.steps,
  });

  factory Leg.fromJson(Map<String, dynamic> json) => Leg(
    arrivalTime: Bounds.fromJson(json["arrival_time"]),
    departureTime: Bounds.fromJson(json["departure_time"]),
    distance: Bounds.fromJson(json["distance"]),
    duration: Bounds.fromJson(json["duration"]),
    endAddress: json["end_address"],
    endLocation: Bounds.fromJson(json["end_location"]),
    startAddress: json["start_address"],
    startLocation: Bounds.fromJson(json["start_location"]),
    steps: List<Step>.from(json["steps"].map((x) => Step.fromJson(x))),
  );

  Map<String, dynamic> toJson() => {
    "arrival_time": arrivalTime.toJson(),
    "departure_time": departureTime.toJson(),
    "distance": distance.toJson(),
    "duration": duration.toJson(),
    "end_address": endAddress,
    "end_location": endLocation.toJson(),
    "start_address": startAddress,
    "start_location": startLocation.toJson(),
    "steps": List<dynamic>.from(steps.map((x) => x.toJson())),
  };
}

class Step {
  Distance distance;
  Distance duration;
  Location endLocation;
  String htmlInstructions;
  Polyline polyline;
  Location startLocation;
  String travelMode;
  List<Step> steps;

  Step({
    this.distance,
    this.duration,
    this.endLocation,
    this.htmlInstructions,
    this.polyline,
    this.startLocation,
    this.travelMode,
    this.steps,
  });

  factory Step.fromJson(Map<String, dynamic> json) => Step(
    distance: Distance.fromJson(json["distance"]),
    duration: Distance.fromJson(json["duration"]),
    endLocation: Location.fromJson(json["end_location"]),
    htmlInstructions: json["html_instructions"],
    polyline: Polyline.fromJson(json["polyline"]),
    startLocation: Location.fromJson(json["start_location"]),
    travelMode: json["travel_mode"],
    steps: json["steps"] == null ? null : List<Step>.from(json["steps"].map((x) => Step.fromJson(x))),
  );

  Map<String, dynamic> toJson() => {
    "distance": distance.toJson(),
    "duration": duration.toJson(),
    "end_location": endLocation.toJson(),
    "html_instructions": htmlInstructions,
    "polyline": polyline.toJson(),
    "start_location": startLocation.toJson(),
    "travel_mode": travelMode,
    "steps": steps == null ? null : List<dynamic>.from(steps.map((x) => x.toJson())),
  };
}

class Distance {
  String text;
  int value;

  Distance({
    this.text,
    this.value,
  });

  factory Distance.fromJson(Map<String, dynamic> json) => Distance(
    text: json["text"],
    value: json["value"],
  );

  Map<String, dynamic> toJson() => {
    "text": text,
    "value": value,
  };
}

class Location {
  double lat;
  double lng;

  Location({
    this.lat,
    this.lng,
  });

  factory Location.fromJson(Map<String, dynamic> json) => Location(
    lat: json["lat"].toDouble(),
    lng: json["lng"].toDouble(),
  );

  Map<String, dynamic> toJson() => {
    "lat": lat,
    "lng": lng,
  };
}

class Polyline {
  String points;

  Polyline({
    this.points,
  });

  factory Polyline.fromJson(Map<String, dynamic> json) => Polyline(
    points: json["points"],
  );

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

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        // This is the theme of your application.
        //
        // Try running your application with "flutter run". You'll see the
        // application has a blue toolbar. Then, without quitting the app, try
        // changing the primarySwatch below to Colors.green and then invoke
        // "hot reload" (press "r" in the console where you ran "flutter run",
        // or simply save your changes to "hot reload" in a Flutter IDE).
        // Notice that the counter didn't reset back to zero; the application
        // is not restarted.
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  // This widget is the home page of your application. It is stateful, meaning
  // that it has a State object (defined below) that contains fields that affect
  // how it looks.

  // This class is the configuration for the state. It holds the values (in this
  // case the title) provided by the parent (in this case the App widget) and
  // used by the build method of the State. Fields in a Widget subclass are
  // always marked "final".

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;
  String jsonString = '''
  {
"geocoded_waypoints":[  ],
   "routes":[ 
      { 
         "bounds":{  },
         "copyrights":"Map data ©2019 Google",
         "legs":[ 
            { 
               "arrival_time":{  },
               "departure_time":{  },
               "distance":{  },
               "duration":{  },
               "end_address":"dsfsfsdf32434324",
               "end_location":{  },
               "start_address":"123123123123adsfdsfsdfsd",
               "start_location":{  },
               "steps":[ 
                  { 
                     "distance":{ 
                              "text":"55 m",
                              "value":55
                           },
                           "duration":{ 
                              "text":"1 min",
                              "value":52
                           },
                           "end_location":{ 
                              "lat":1.3775668,
                              "lng":103.8481395
                           },
                           "html_instructions":"Head" ,
                           "polyline":{ 
                              "points":"galGu|yxRH|@BZ"
                           },
                           "start_location":{ 
                              "lat":122,
                              "lng":1231
                           },
                           "travel_mode":"WALKING",
                     "steps":[ 
                        { 
                           "distance":{ 
                              "text":"55 m",
                              "value":55
                           },
                           "duration":{ 
                              "text":"1 min",
                              "value":52
                           },
                           "end_location":{ 
                              "lat":1.3775668,
                              "lng":103.8481395
                           },
                           "html_instructions":"Head" ,
                           "polyline":{ 
                              "points":"galGu|yxRH|@BZ"
                           },
                           "start_location":{ 
                              "lat":122,
                              "lng":1231
                           },
                           "travel_mode":"WALKING"
                        }
                        ]
                        }]
                        }]
                        }]
                        }

  ''';
  void _incrementCounter() {

    Payload payload = payloadFromJson(jsonString);
    print( ' ${payload.routes[0].legs[0].steps[0].distance.text}' );
    print( ' ${payload.routes[0].legs[0].steps[0].steps[0].distance.text}' );

    setState(() {
      // This call to setState tells the Flutter framework that something has
      // changed in this State, which causes it to rerun the build method below
      // so that the display can reflect the updated values. If we changed
      // _counter without calling setState(), then the build method would not be
      // called again, and so nothing would appear to happen.
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    // This method is rerun every time setState is called, for instance as done
    // by the _incrementCounter method above.
    //
    // The Flutter framework has been optimized to make rerunning build methods
    // fast, so that you can just rebuild anything that needs updating rather
    // than having to individually change instances of widgets.
    return Scaffold(
      appBar: AppBar(
        // Here we take the value from the MyHomePage object that was created by
        // the App.build method, and use it to set our appbar title.
        title: Text(widget.title),
      ),
      body: Center(
        // Center is a layout widget. It takes a single child and positions it
        // in the middle of the parent.
        child: Column(
          // Column is also a layout widget. It takes a list of children and
          // arranges them vertically. By default, it sizes itself to fit its
          // children horizontally, and tries to be as tall as its parent.
          //
          // Invoke "debug painting" (press "p" in the console, choose the
          // "Toggle Debug Paint" action from the Flutter Inspector in Android
          // Studio, or the "Toggle Debug Paint" command in Visual Studio Code)
          // to see the wireframe for each widget.
          //
          // Column has various properties to control how it sizes itself and
          // how it positions its children. Here we use mainAxisAlignment to
          // center the children vertically; the main axis here is the vertical
          // axis because Columns are vertical (the cross axis would be
          // horizontal).
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.display1,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}