2

In this Project App is receiving posts from a WP REST API as JSON, it works fine, but I need to convert it to an Item Model (for caching and DB): so I created an Item-Model, now how can I implement it in my code, which gets String. how can I Map my data in getPosts() so it returns a Post, not a String? please, Please show me the way in CODE.

// Function to get list of posts which is String
 Future<String> getPosts() async {
 var res = await http.get(Uri.encodeFull(apiUrl + "posts?_embed&per_page=10"),
 headers: {"Accept": "application/json"});
 setState(() {
 var resBody = json.decode(res.body);

 posts = resBody;
});

return "Success!";
}

Future builder to show a Loading indicator before loading posts:

 body: FutureBuilder<List<String>>(
  future: getPosts(),
  builder: (context, snapshot) {
    if (snapshot.hasError) print(snapshot.error);

    return snapshot.hasData
        ? ListViewPosts(posts: snapshot.data)
        : Center(child: CircularProgressIndicator());
  },
),

Code for ItemModel

class Post {
  int _id;
  String _title;
  String _content;
  String _author;
  String _date;
  String _imgUrl;

  Post(this._id, this._title, this._content, this._author, this._date,
      [this._imgUrl]);

  Post.withId(this._id, this._title, this._content, this._author, this._date,
      [this._imgUrl]);

  int get id => _id;
  String get title => _title;
  String get content => _content;
  String get author => _author;
  String get date => _date;
  String get imgUrl => _imgUrl;

  set title(String newTitle) {
    this._title = newTitle;
  }

  set content(String newContent) {
    this._content = newContent;
  }

  set author(String newAuthor) {
    this._author = newAuthor;
  }

  set date(String newDate) {
    this._date = newDate;
  }

  set imgUrl(String newImgUrl) {
    this._imgUrl = newImgUrl;
  }

  //convert post to Map
  Map<String, dynamic> toMap() {
    var map = Map<String, dynamic>();

    if (id != null) {
      map['id'] = _id;
    }
    map['title'] = _title;
    map['content'] = _content;
    map['author'] = _author;
    map['date'] = _date;
    map['imgurl'] = _imgUrl;
    return map;
  }

  //Extract post from Map Object
  Post.fromMapObject(Map<String, dynamic> map) {
    this._id = map['id'];
    this._title = map['title'];
    this._content = map['content'];
    this._author = map['author'];
    this._date = map['date'];
    this._imgUrl = map['imgurl'];
  }
}

the JSON response

{ 
     "id": 73331,
    "date": "2018-11-24T19:00:21",
    "date_gmt": "2018-11-24T19:00:21",
    "guid": {
        "rendered": "theUrl?p=73331"
    },
    "modified": "2018-11-24T19:00:21",
    "modified_gmt": "2018-11-24T19:00:21",
    "slug": "%d8%aa%db%8e%d8%b3%d8%aa-%d8%a8%d9%88-%d9%be%d9%87%e2%80%8c%da%95%db%8c-%d8%b3%d9%87%e2%80%8c%d8%b1%d9%87%e2%80%8c%d9%83%db%8c",
    "status": "publish",
    "type": "post",
    "link": "theUrl/2018/11/24/%d8%aa%db%8e%d8%b3%d8%aa-%d8%a8%d9%88-%d9%be%d9%87%e2%80%8c%da%95%db%8c-%d8%b3%d9%87%e2%80%8c%d8%b1%d9%87%e2%80%8c%d9%83%db%8c/",
    "title": {
        "rendered": "تێست بو په\u200cڕی سه\u200cره\u200cكی"
    },
    "content": {
        "rendered": "<p>تێست بو په\u200cڕی سه\u200cره\u200cكی تێست بو په\u200cڕی سه\u200cره\u200cكی تێست بو په\u200cڕی سه\u200cره\u200cكی تێست بو په\u200cڕی سه\u200cره\u200cكی تێست بو په\u200cڕی سه\u200cره\u200cكی</p>\n<div class=\"likebtn_container\" style=\"\"><!-- LikeBtn.com BEGIN --><span class=\"likebtn-wrapper\"  data-identifier=\"post_73331\"  data-theme=\"large\"  data-lang=\"ck\"  data-ef_voting=\"buzz\"  data-tooltip_enabled=\"false\"  data-white_label=\"true\"  data-rich_snippet=\"true\"  data-popup_disabled=\"true\"  data-style=\"\"  data-unlike_allowed=\"\"  data-show_copyright=\"\"  data-item_url=\"theUrl/2018/11/24/%d8%aa%db%8e%d8%b3%d8%aa-%d8%a8%d9%88-%d9%be%d9%87%e2%80%8c%da%95%db%8c-%d8%b3%d9%87%e2%80%8c%d8%b1%d9%87%e2%80%8c%d9%83%db%8c/\"  data-item_title=\"تێست بو په\u200cڕی سه\u200cره\u200cكی\"  data-item_image=\"theUrl/wp-content/uploads/2018/11/IMG_5203-1024x620.jpg\"  data-item_date=\"2018-11-24T19:00:21+00:00\"  data-engine=\"WordPress\"  data-plugin_v=\"2.6.11\"  data-event_handler=\"likebtn_eh\" ></span><!-- LikeBtn.com END --></div>",
        "protected": false
    },
    "excerpt": {
        "rendered": "<p>تێست بو په\u200cڕی سه\u200cره\u200cكی تێست بو په\u200cڕی سه\u200cره\u200cكی تێست بو په\u200cڕی سه\u200cره\u200cكی تێست بو په\u200cڕی سه\u200cره\u200cكی تێست بو په\u200cڕی سه\u200cره\u200cكی</p>\n<div class=\"likebtn_container\" style=\"\"><!-- LikeBtn.com BEGIN --><span class=\"likebtn-wrapper\"  data-identifier=\"post_73331\"  data-theme=\"large\"  data-lang=\"ck\"  data-ef_voting=\"buzz\"  data-tooltip_enabled=\"false\"  data-white_label=\"true\"  data-rich_snippet=\"true\"  data-popup_disabled=\"true\"  data-style=\"\"  data-unlike_allowed=\"\"  data-show_copyright=\"\"  data-item_url=\"theUrl/2018/11/24/%d8%aa%db%8e%d8%b3%d8%aa-%d8%a8%d9%88-%d9%be%d9%87%e2%80%8c%da%95%db%8c-%d8%b3%d9%87%e2%80%8c%d8%b1%d9%87%e2%80%8c%d9%83%db%8c/\"  data-item_title=\"تێست بو په\u200cڕی سه\u200cره\u200cكی\"  data-item_image=\"theUrl/wp-content/uploads/2018/11/IMG_5203-1024x620.jpg\"  data-item_date=\"2018-11-24T19:00:21+00:00\"  data-engine=\"WordPress\"  data-plugin_v=\"2.6.11\"  data-event_handler=\"likebtn_eh\" ></span><!-- LikeBtn.com END --></div>",
        "protected": false
    },
    "author": 1,
    "featured_media": 73332,
    "comment_status": "open",
    "ping_status": "open",
    "sticky": false,
    "template": "",
    "format": "standard",
    "meta": [],
    "categories": [
        1
    ],
    "tags": [],
    "acf": [],
    "_links": {
        "self": [
            {
                "href": "theUrl/wp-json/wp/v2/posts/73331"
            }
        ],
        "collection": [
            {
                "href": "theUrl/wp-json/wp/v2/posts"
            }
        ],
        "about": [
            {
                "href": "theUrl/wp-json/wp/v2/types/post"
            }
        ],
        "author": [
            {
                "embeddable": true,
                "href": "theUrl/wp-json/wp/v2/users/1"
            }
        ],
        "replies": [
            {
                "embeddable": true,
                "href": "theUrl/wp-json/wp/v2/comments?post=73331"
            }
        ],
    }
5
  • Can you provide an example of the JSON response please? Commented Nov 27, 2018 at 16:22
  • I have added it in the above code. thanx Basically {"id": id, "title":title, "content":contentasText, img ... etc Commented Nov 27, 2018 at 17:21
  • Sounds like you're looking for this: pub.dartlang.org/packages/json_annotation It'll generate the mapping code for you. Commented Nov 27, 2018 at 17:55
  • If the answer below answered your question please mark it as the accepted answer. If not please provide some comment on it. Commented Nov 27, 2018 at 21:31
  • Just working on it now but without using json_annotation. @Hooshyar there doesn't seem to be an imgUrl field in the JSON. Do you mean the img url given within the content or excerpt rendered? Commented Nov 28, 2018 at 9:15

2 Answers 2

2

You would most likely want to use a serialization library. In dart, which is what runs Flutter, a common one is json_serializable.

EXAMPLE

Step 1

I'm taking their example for reference:

Given a library example.dart with an Person class annotated with @JsonSerializable():

import 'package:json_annotation/json_annotation.dart';

part 'example.g.dart';

@JsonSerializable(nullable: false)
class Person {
  final String firstName;
  final String lastName;
  final DateTime dateOfBirth;
  Person({this.firstName, this.lastName, this.dateOfBirth});
  factory Person.fromJson(Map<String, dynamic> json) => _$PersonFromJson(json);
  Map<String, dynamic> toJson() => _$PersonToJson(this);
}

Note that in dart files suffix in g.dart are generated by the build system.

Step 2

Convert to map

import 'dart:convert';
...
Map valueMap = json.decode(value);

Step 3

Deserialize

Person person = Person.from(valueMap)

INSTALL

To install, you simply add this to your pubspec.yml:

dependencies:
  ...
  json_annotation: ^1.2.0

dev_dependencies:
  build_runner: ^0.10.3

Then run flutter packages get

Sign up to request clarification or add additional context in comments.

1 Comment

thanks, I stumbled upon json_serilizable but it wasn't easy to learn and implement it into my project was complicated.
0

Here's how I converted the JSON into an object without using json_annotation:

Post and PostViewModel classes:

import 'dart:convert';
import 'dart:async' show Future;
import 'package:flutter/services.dart' show rootBundle;

class Post {
  final int id;
  final String title;
  final String content;
  final String author;
  final String date;
  final String imgUrl;

  Post(
      {this.id, this.title, this.content, this.author,this.date, this.imgUrl});

  factory Post.fromJson(Map<String, dynamic> json) {
    List<String> contents = json['content']['rendered'].toString().split('"');

    return Post(
        id: json['id'],
        title: json['title']['rendered'],
        content: json['content']['rendered'],
        author: json['_links']['author'][0]['href'],
        date: json['date'],
        imgUrl: contents[33]
    );
  }
}

class PostViewModel {
  static Post post;

  static Future<Post> loadData() async {
    post = new Post();
    try {
      String jsonData = await rootBundle.loadString('assets/data.json');
      post = new Post.fromJson(json.decode(jsonData));
    } catch (e) {
      print(e);
    }
    return post;
  }
}

HomePage to demo info:

import 'package:flutter/material.dart';
import 'package:hello_world/post.dart';

class HomePage extends StatefulWidget {

  @override
  HomePageState createState() => new HomePageState();

}

class HomePageState extends State<HomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(title: Text("Home")),
        body: Material(
            child: Column(children: <Widget>[
              Text(PostViewModel.post.id.toString()),
              Text(PostViewModel.post.title),
              Text(PostViewModel.post.author),
              Text(PostViewModel.post.date),
              Text(PostViewModel.post.imgUrl),
              Text(PostViewModel.post.content)
            ])));
  }
}

Image:

enter image description here

Just noting that I couldn't find an imgUrl field in the JSON provided but I presumed it was the image Url given within the content[rendered] field so used that.

1 Comment

I think the best solution for larger projects will be Json Serilization, but thats so complicated , creating the file .g.dart an etc, im trying to learn that.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.