Как конвертировать JSON -LD в объект dart - PullRequest
1 голос
/ 22 апреля 2020

Я использую Symfony Платформа API и Flutter для веб-проекта. Api возвращает формат JSON -LD следующим образом:

enter image description here

, но я получил эту ошибку:

enter image description here

Для проекта флаттера, я следовал документации https://flutter.dev/docs/cookbook/networking/fetch-data:

Учебник:

class Book {
final int id;
final String isbn;
final String title;

  Book({this.id, this.isbn, this.title});

  factory Book.fromJson(Map<String, dynamic> json) {
    return Book(
      id: json['id'] as int,
      isbn: json['isbn'] as String,
      title: json['title'] as String,
    );
  }

}

Это book_http_service.dart:

class BookHttpService {
  Future<Book> listBooks() async {
    final response = await http.get('http://192.168.1.13:8000/api/books');

    if (response.statusCode == 200) {
      // If the server did return a 200 OK response,
      // then parse the JSON.
      return Book.fromJson(json.decode(response.body));
    } else {
      // If the server did not return a 200 OK response,
      // then throw an exception.
      throw Exception('Failed to load books');
    }
  }
}

А это интерфейс для отображения книг ( book_list.dart )

class _BookState extends State<BookList> {
  final BookHttpService bookHttpService = BookHttpService();

  @override
  Widget build(BuildContext context) {
    return Container(
      child: FutureBuilder<Book>(
        future: bookHttpService.listBooks(),
        builder: (context, snapshot) {
          if (snapshot.hasData) {
            return Text(snapshot.data.title);
          } else if (snapshot.hasError) {
            return Text("${snapshot.error.toString()}");
          }

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

Ответы [ 2 ]

2 голосов
/ 22 апреля 2020

Вы можете скопировать и вставить полный код ниже
Вы можете увидеть Book класс в полном коде
Шаг 1: Предположим, что ваша строка json выглядит следующим образом

 String jsonString = '''
    {
 "@context": "api/contexts/Book",
 "@id":"api/books",
 "@type":"hydra:Collection",
 "hydra:member":[
 {
   "@id": "api/books/2",
   "@type": "Book",
   "id":2,
   "isbn":"8545",
   "title":"test body",
   "author":"abc",
   "pubLicationDate":"2020-01-14T16:29:16+01:00",
   "active":false,
   "owner":null
 },
 {
   "@id": "api/books/2",
   "@type": "Book",
   "id":1,
   "isbn":"1234",
   "title":"test body 2",
   "author":"def",
   "pubLicationDate":"2020-01-14T16:29:16+01:00",
   "active":false,
   "owner":null
 }
 ]
}
    ''';

Шаг 2 : анализ с bookFromJson(response.body);
Шаг 3: отображение данных с ListView

FutureBuilder<Book>(
          future: _future,
          builder: (context, snapshot) {
            if (snapshot.hasData) {
              return ListView.builder(
                  padding: const EdgeInsets.all(8),
                  itemCount: snapshot.data.hydraMember.length,
                  itemBuilder: (BuildContext context, int index) {
                    return Container(
                      height: 50,
                      child: Center(
                          child:
                              Text('${snapshot.data.hydraMember[index].title}'))

рабочая демонстрация

enter image description here

полный код

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

Book bookFromJson(String str) => Book.fromJson(json.decode(str));

String bookToJson(Book data) => json.encode(data.toJson());

class Book {
  String context;
  String id;
  String type;
  List<HydraMember> hydraMember;

  Book({
    this.context,
    this.id,
    this.type,
    this.hydraMember,
  });

  factory Book.fromJson(Map<String, dynamic> json) => Book(
        context: json["@context"],
        id: json["@id"],
        type: json["@type"],
        hydraMember: List<HydraMember>.from(
            json["hydra:member"].map((x) => HydraMember.fromJson(x))),
      );

  Map<String, dynamic> toJson() => {
        "@context": context,
        "@id": id,
        "@type": type,
        "hydra:member": List<dynamic>.from(hydraMember.map((x) => x.toJson())),
      };
}

class HydraMember {
  String id;
  String type;
  int hydraMemberId;
  String isbn;
  String title;
  String author;
  DateTime pubLicationDate;
  bool active;
  dynamic owner;

  HydraMember({
    this.id,
    this.type,
    this.hydraMemberId,
    this.isbn,
    this.title,
    this.author,
    this.pubLicationDate,
    this.active,
    this.owner,
  });

  factory HydraMember.fromJson(Map<String, dynamic> json) => HydraMember(
        id: json["@id"],
        type: json["@type"],
        hydraMemberId: json["id"],
        isbn: json["isbn"],
        title: json["title"],
        author: json["author"],
        pubLicationDate: DateTime.parse(json["pubLicationDate"]),
        active: json["active"],
        owner: json["owner"],
      );

  Map<String, dynamic> toJson() => {
        "@id": id,
        "@type": type,
        "id": hydraMemberId,
        "isbn": isbn,
        "title": title,
        "author": author,
        "pubLicationDate": pubLicationDate.toIso8601String(),
        "active": active,
        "owner": owner,
      };
}

class BookHttpService {
  Future<Book> listBooks() async {
    //final response = await http.get('http://192.168.1.13:8000/api/books');
    String jsonString = '''
    {
 "@context": "api/contexts/Book",
 "@id":"api/books",
 "@type":"hydra:Collection",
 "hydra:member":[
 {
   "@id": "api/books/2",
   "@type": "Book",
   "id":2,
   "isbn":"8545",
   "title":"test body",
   "author":"abc",
   "pubLicationDate":"2020-01-14T16:29:16+01:00",
   "active":false,
   "owner":null
 },
 {
   "@id": "api/books/2",
   "@type": "Book",
   "id":1,
   "isbn":"1234",
   "title":"test body 2",
   "author":"def",
   "pubLicationDate":"2020-01-14T16:29:16+01:00",
   "active":false,
   "owner":null
 }
 ]
}
    ''';

    final response = http.Response(jsonString, 200);

    if (response.statusCode == 200) {
      // If the server did return a 200 OK response,
      // then parse the JSON.
      return bookFromJson(response.body);
    } else {
      // If the server did not return a 200 OK response,
      // then throw an exception.
      throw Exception('Failed to load books');
    }
  }
}

class BookList extends StatefulWidget {
  @override
  _BookListState createState() => _BookListState();
}

class _BookListState extends State<BookList> {
  Future _future;
  final BookHttpService bookHttpService = BookHttpService();

  @override
  void initState() {
    _future = bookHttpService.listBooks();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Test'),
      ),
      body: Container(
        child: FutureBuilder<Book>(
          future: _future,
          builder: (context, snapshot) {
            if (snapshot.hasData) {
              return ListView.builder(
                  padding: const EdgeInsets.all(8),
                  itemCount: snapshot.data.hydraMember.length,
                  itemBuilder: (BuildContext context, int index) {
                    return Container(
                      height: 50,
                      child: Center(
                          child:
                              Text('${snapshot.data.hydraMember[index].title}')),
                    );
                  });
            } else if (snapshot.hasError) {
              return Text("${snapshot.error.toString()}");
            }

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

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: BookList(),
    );
  }
}
0 голосов
/ 22 апреля 2020

Я создал короткий скрипт на основе примеров Sqlite , и он хорошо работает:

Учебник:

class Book {
  String schemaContext;
  String schemaId;
  String schemaType;
  int id;
  String title;

  Book({
    this.schemaContext,
    this.schemaId,
    this.schemaType,
    this.id,
    this.title,
  });

  factory Book.fromJson(schema, Map<String, dynamic> json) => Book(
        schemaContext: schema['@context'],
        schemaId: schema['@id'],
        schemaType: schema['@type'],
        id: json["id"],
        title: json["title"],
      );

}

BookHttpService:

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

import 'package:book_app/models/book.dart';

class BookHttpService {
  Future<List<Book>> listBooks() async {
    final response = await http.get('http://192.168.1.13:8000/api/books');

    if (response.statusCode == 200) {
      var result = json.decode(response.body);
      return List.generate(result['hydra:member'].length, (i) {
        return Book.fromJson(result, result['hydra:member'][i]);
      });
    } else {
      // If the server did not return a 200 OK response,
      // then throw an exception.
      throw Exception('Failed to load books');
    }
  }
}

book_list.dart:

class _BookState extends State<BookList> {
  final BookHttpService bookHttpService = BookHttpService();

  List<Book> books;
  Book book;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('List books'),
        centerTitle: true,
      ),
      body: Container(
        child: FutureBuilder(
          future: bookHttpService.listBooks(),
          builder: (context, snapshot) {
            books = snapshot.data;
            if (snapshot.hasData) {
              return ListView.builder(
                shrinkWrap: true,
                itemCount: books.length,
                itemBuilder: (context, int index) {
                  book = books[index];
                  return Padding(
                    padding: const EdgeInsets.symmetric(
                        vertical: 1.0, horizontal: 4.0),
                    child: Card(
                      child: ListTile(
                        onTap: () {},
                        title: RichText(
                          text: TextSpan(
                            text: book.title,
                            style: TextStyle(
                                fontWeight: FontWeight.bold,
                                color: Colors.black,
                                fontSize: 15.0),
                          ),
                        ),
                      ),
                    ),
                  );
                },
              );
            } else if (snapshot.hasError) {
              return Text("error");
            }

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