如何将 JSON-LD 转换为飞镖对象
How to convert JSON-LD to dart object
我正在为 Web 项目使用 Symfony API 平台和 Flutter。 Api returns JSON-LD 格式如下:
但是我得到了这个错误:
关于flutter projcet,我已经按照文档https://flutter.dev/docs/cookbook/networking/fetch-data :
Class 书:
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();
},
),
);
}
}
您可以复制粘贴 运行 下面的完整代码
你可以看到完整代码 Book
class
第 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);
解析
第三步:用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}'))
工作演示
完整代码
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(),
);
}
}
我根据 Sqlite 的例子创建了一个简短的脚本,效果很好:
Class 书:
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();
},
),
),
);
}
}
我正在为 Web 项目使用 Symfony API 平台和 Flutter。 Api returns JSON-LD 格式如下:
但是我得到了这个错误:
关于flutter projcet,我已经按照文档https://flutter.dev/docs/cookbook/networking/fetch-data :
Class 书:
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();
},
),
);
}
}
您可以复制粘贴 运行 下面的完整代码
你可以看到完整代码 Book
class
第 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);
解析
第三步:用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}'))
工作演示
完整代码
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(),
);
}
}
我根据 Sqlite 的例子创建了一个简短的脚本,效果很好:
Class 书:
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();
},
),
),
);
}
}