source

flutter에 있는 json의 객체 목록을 역직렬화하는 방법

nicesource 2023. 2. 28. 23:38
반응형

flutter에 있는 json의 객체 목록을 역직렬화하는 방법

json serialization에는 dart 패키지 json_serializable을 사용하고 있습니다.플래터 매뉴얼을 보면 다음과 같이 단일 개체를 역직렬화하는 방법이 나와 있습니다.

Future<Post> fetchPost() async {
  final response =
  await http.get('https://jsonplaceholder.typicode.com/posts/1');

  if (response.statusCode == 200) {
  // If the call to the server was successful, parse the JSON
  return Post.fromJson(json.decode(response.body));
  } else {
    // If that call was not successful, throw an error.
    throw Exception('Failed to load post');
  }
}

단, 다트는 단일 인스턴스가 아닌 항목 목록에 대해 동일한 작업을 수행하는 방법을 이해할 수 없을 정도로 익숙하지 않습니다.

대응 기구가 지도이거나 그에 따라 지도 목록을 처리하는 서비스입니다.당신이 가지고 있는 코드로 계산하면 당신은 1개의 아이템을 계산하고 있습니다.

응답 본문이 반복할 수 있는 경우, 내가 당신의 질문을 올바르게 이해하고 있다면 그에 따라 해석하고 걸어야 합니다.

예:

Iterable l = json.decode(response.body);
List<Post> posts = List<Post>.from(l.map((model)=> Post.fromJson(model)));

여기서 post는 투고 목록입니다.

편집: 여기에 명료한 메모를 추가하고 싶습니다.여기서의 목적은 반환된 응답을 디코딩하는 것입니다.다음 단계에서는 JSON 오브젝트의 반복 가능한 인스턴스를 오브젝트의 인스턴스로 변환합니다.이는 클래스 내에서 JSON 메서드를 생성하여 적절하게 JSON을 구현함으로써 이루어집니다.다음으로 구현 예를 제시하겠습니다.

class Post {
  // Other functions and properties relevant to the class
  // ......
  /// Json is a Map<dynamic,dynamic> if i recall correctly.
  static fromJson(json): Post {
    Post p = new Post()
    p.name = ...
    return p
  }
}

나는 요즘 다트에서 좀 더 나은 유틸리티로 해야 할 일을 하는 것에 대해 추상적이다.구문이 조금 어긋난 것 같습니다만, 이것은 의사 코드입니다.

항상 문제없이 사용하고 있습니다.

List<MyModel> myModels;
var response = await http.get("myUrl");

myModels=(json.decode(response.body) as List).map((i) =>
              MyModel.fromJson(i)).toList();

당신은 또한 그것을 할 수 있습니다.

  List<dynamic> parsedListJson = jsonDecode("your json string");
  List<Item> itemsList = List<Item>.from(parsedListJson.map<Item>((dynamic i) => Item.fromJson(i)));

서 ''는Item이에서는, 「커스텀 클래스」를 .이 클래스에서는toJson ★★★★★★★★★★★★★★★★★」fromJson.

자세한 설명을 위해 JSON 파싱의 또 다른 예를 제시하겠습니다.

예를 들어 JSON 오브젝트의 아이템 배열을 해석한다고 합시다.

factory YoutubeResponse.fromJSON(Map<String, dynamic> YoutubeResponseJson) 
 {

// Below 2 line code is parsing JSON Array of items in our JSON Object (YouttubeResponse)


var list = YoutubeResponseJson['items'] as List;
List<Item> itemsList = list.map((i) => Item.fromJSON(i)).toList();

return new YoutubeResponse(
    kind: YoutubeResponseJson['kind'],
    etag: YoutubeResponseJson['etag'],
    nextPageToken: YoutubeResponseJson['nextPageToken'],
    regionCode: YoutubeResponseJson['regionCode'],
    mPageInfo: pageInfo.fromJSON(YoutubeResponseJson['pageInfo']),

    // Here we are returning parsed JSON Array.

    items: itemsList);

  }

데이터와 저 같은 json이라고 하는 이름의 합니다).이 경우 다음 이름을 가진 클래스를 만듭니다(생성합니다.Img:

import 'dart:convert';

Img imgFromJson(String str) => Img.fromJson(json.decode(str));
String imgToJson(Img data) => json.encode(data.toJson());

class Img {
    String id;
    String img;
    dynamic decreption;

    Img({
        this.id,
        this.img,
        this.decreption,
    });

    factory Img.fromJson(Map<String, dynamic> json) => Img(
        id: json["id"],
        img: json["img"],
        decreption: json["decreption"],
    );

    Map<String, dynamic> toJson() => {
        "id": id,
        "img": img,
        "decreption": decreption,
    };
}

추신. 앱을 사용할 수 있습니다.quicktype.io에서 json 데이터 클래스를 dart로 생성하고 게시물을 서버로 전송합니다.

Future<List<Img>> _getimages() async {
    var response = await http.get("http://192.168.115.2/flutter/get_images.php");
    var rb = response.body;

    // store json data into list
    var list = json.decode(rb) as List;

    // iterate over the list and map each object in list to Img by calling Img.fromJson
    List<Img> imgs = list.map((i)=>Img.fromJson(i)).toList();

    print(imgs.runtimeType); //returns List<Img>
    print(imgs[0].runtimeType); //returns Img

    return imgs;
}

자세한 내용은 Flutter의 복잡한 JSON 구문 분석을 참조하십시오.

완전한 예

오브젝트 리스트의 JSON 시리얼화 및 역직렬화의 완전한 예를 다음에 나타냅니다.< Object >여기에는 네스트된 서브클래스와 리스트<서브>로 구성된 메인클래스가 있습니다.

Json 표본

{
    "title": "something",
    "sub": {"name": "a", "num": 0},
    "sub_list": [
      {"name": "b", "num": 1},
      {"name": "c", "num": 2}
    ]
}

메인 클래스

class Main {
  String title;
  Sub sub;
  List<Sub> subList;

  Main(this.title, this.sub, this.subList);

  Main.fromJson(Map<String, dynamic> json)
      : title = json['title'],
        sub = Sub.fromJson(json['sub']),
        subList = List<dynamic>.from(json['sub_list'])
            .map((i) => Sub.fromJson(i))
            .toList();

  Map<String, dynamic> toJson() => {
        'title': title,
        'sub': sub.toJson(),
        'sub_list': subList.map((item) => item.toJson()).toList(),
      };
}

서브클래스

class Sub {
  String name;
  int n;

  Sub(this.name, this.n);

  Sub.fromJson(Map<String, dynamic> json)
      : name = json['name'],
        n = json['n'];

  Map<String, dynamic> toJson() => {
        'name': name,
        'n': n,
      };
}

사용.

void main(List<String> args) {
  var sub = Sub("a", 0);
  print(sub.name); // a

  Map<String, dynamic> jsonSub = {"name": "a", "n": 0};
  var subFromJson = Sub.fromJson(jsonSub);
  print(subFromJson.n); // 0

  var main = Main("something", Sub("a", 0), [Sub("b", 1)]);
  print(main.title); // something
  print(main.sub.name); // a
  print(main.subList[0].name); // b

  var jsonMain = {
    "title": "something",
    "sub": {"name": "a", "n": 0},
    "sub_list": [
      {"name": "b", "n": 1},
      {"name": "c", "n": 2}
    ]
  };
  var mainFromJson = Main.fromJson(jsonMain);
  print(mainFromJson.title); // something
  print(mainFromJson.sub.name); // a
  print(mainFromJson.subList[0].name); // b
  print(mainFromJson.subList[1].name); // c
}

하다

  1. 모델 클래스(LoginResponse)를 만듭니다.json을 dart로 변환하려면 여기를 클릭하십시오.

  2. LoginResponce loginResponce=LoginResponce.fromJson(json.decode(response.body));

  3. 이제 모델(loginResponce)에서 데이터를 얻을 수 있습니다.

strong-mode를 유효하게 하면, 타입 정보가 없기 때문에, 상기의 솔루션은 실제로는 컴파일 되지 않습니다.

이것은 dart 2.14 시점에서 strong 모드가 유효하게 되어 컴파일 됩니다.

analysis_discl.discl


include: package:lints/recommended.yaml

analyzer:
  strong-mode:
    implicit-casts: false
    implicit-dynamic: false

    import 'dart:convert';

    // read the json file. This example use dcli but you just
    // need [source] to contain the json string.
    var source = dcli.read(_failedTrackerFilename).toParagraph();

    var l = json.decode(source) as Iterable;
    var failures = List<UnitTest>.from(l.map<UnitTest>(
          (dynamic i) => UnitTest.fromJson(i as Map<String, dynamic>)));

모델 클래스입니다.

  class SuggestedMovie {
  String title;
  String genres;
  int movieId;
  SuggestedMovie({this.title, this.genres, this.movieId});
  factory SuggestedMovie.fromJson(Map<dynamic, dynamic> parsedJson) {
    return SuggestedMovie(
      movieId: parsedJson['movieId'],
      title: parsedJson['title'] as String,
      genres: parsedJson['genres'] as String,
    );
  }
}

다음 코드는 JSON 응답을 목록으로 역직렬화하는 코드입니다.

 suggestedMovie = (json.decode(jsonResponse.data) as List)
      .map((i) => SuggestedMovie.fromJson(i))
      .toList();

flutter에 있는 json의 객체 목록을 역직렬화하는 방법

역직렬화JSONSerializer.
코드 생성 예:

import 'dart:io';

import 'package:object_serializer/json_serializer_generator.dart';
import 'package:yaml/yaml.dart';

void main() {
  final classes = loadYaml(_classes) as Map;
  final g = JsonSerializerGenerator();
  final classesCode = g.generateClasses(classes);

  final values = {
    'classes': classesCode,
  };

  var source = g.render(_template, values);
  source = g.format(source);
  File('bin/stackoverflow.dart').writeAsStringSync(source);
}

const _classes = '''
Post:
  fields:
    userId: int
    id: int
    title: String
    body: String
''';

const _template = r'''
import 'dart:convert';

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

void main() async {
  final res1 =
      await http.get(Uri.parse('https://jsonplaceholder.typicode.com/posts/1'));
  final post = Post.fromJson(jsonDecode(res1.body) as Map);
  print(post.title);
  final res2 =
      await http.get(Uri.parse('https://jsonplaceholder.typicode.com/posts'));
  final posts = Post.fromJsonList(jsonDecode(res2.body) as List);
  print('Posts: ${posts.length}');
  if (posts.isNotEmpty) {
    print(posts.first.title);
  }
}

{{classes}}
''';

생성된 예의 소스 코드:

import 'dart:convert';

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

void main() async {
  final res1 =
      await http.get(Uri.parse('https://jsonplaceholder.typicode.com/posts/1'));
  final post = Post.fromJson(jsonDecode(res1.body) as Map);
  print(post.title);
  final res2 =
      await http.get(Uri.parse('https://jsonplaceholder.typicode.com/posts'));
  final posts = Post.fromJsonList(jsonDecode(res2.body) as List);
  print('Posts: ${posts.length}');
  if (posts.isNotEmpty) {
    print(posts.first.title);
  }
}

class Post {
  Post(
      {required this.userId,
      required this.id,
      required this.title,
      required this.body});

  factory Post.fromJson(Map json) {
    return Post(
      userId: json['userId'] == null ? 0 : json['userId'] as int,
      id: json['id'] == null ? 0 : json['id'] as int,
      title: json['title'] == null ? '' : json['title'] as String,
      body: json['body'] == null ? '' : json['body'] as String,
    );
  }

  final int userId;

  final int id;

  final String title;

  final String body;

  static List<Post> fromJsonList(List json) {
    return json.map((e) => Post.fromJson(e as Map)).toList();
  }

  Map<String, dynamic> toJson() {
    return {
      'userId': userId,
      'id': id,
      'title': title,
      'body': body,
    };
  }

  static List<Map<String, dynamic>> toJsonList(List<Post> list) {
    return list.map((e) => e.toJson()).toList();
  }
}

때때로 JSON의 구조와 Pojo 클래스에 문제가 발생합니다.

JSON은 다음과 같습니다.

{"records":[{"name":"noor ","email":"email","mobileNo":187,"feedback":"good"}]}

이 JSON에 따르면 올바른 방법으로 pojo 클래스를 만들어야 합니다.JSON을 붙여넣으면 다음 사이트에서 pojo 클래스가 제공됩니다.https://javiercbk.github.io/json_to_dart/

거기에 클래스 이름을 붙여야 합니다.질문의 이름과 함께 위의 JSON에 따라 다음 두 가지 pojo 클래스를 찾았습니다.

class Questions {
  List<Records>? records;

  Questions({this.records});

  Questions.fromJson(Map<String, dynamic> json) {
    if (json['records'] != null) {
      records = <Records>[];
      json['records'].forEach((v) {
        records!.add(new Records.fromJson(v));
      });
    }
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    if (this.records != null) {
      data['records'] = this.records!.map((v) => v.toJson()).toList();
    }
    return data;
  }
}

class Records {
  String? name;
  String? email;
  int? mobileNo;
  String? feedback;

  Records({this.name, this.email, this.mobileNo, this.feedback});

  Records.fromJson(Map<String, dynamic> json) {
    name = json['name'];
    email = json['email'];
    mobileNo = json['mobileNo'];
    feedback = json['feedback'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['name'] = this.name;
    data['email'] = this.email;
    data['mobileNo'] = this.mobileNo;
    data['feedback'] = this.feedback;
    return data;
  }
}

여기서 중요한 것은 레코드를 목록으로 변환하는 것입니다.전화는 다음과 같습니다.

Future<List<Records>> getRecordList() async {
    return await http.get(Uri.parse(URL)).then((response) {
      print(response.body.toString());

      Questions questions = Questions.fromJson(json.decode(response.body));

     

      print(questions.records![0].feedback);

      List<Records> list_s = [];
      for (int i = 0; i < questions.records!.length; i++) {
        list_s.add(questions.records![i]);
      }

      print(list_s[0].name);

      return list_s;
    });
  }
}

마지막으로 UI 부분은 다음과 같습니다.

class _FeedbackListPageState extends State<FeedbackListPage> {
 
  List<Records> list_s = [];
  

  @override
  void initState() {
    super.initState();

    FormController().getRecordList().then((value) {
      setState(() {
        list_s = value;
      });
    });

    
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: darkGreen,
        elevation: 0.0,
        titleSpacing: 10.0,
        title: Text(widget.title),
        centerTitle: true,
        leading: InkWell(
          onTap: () {
            Navigator.pop(context);
          },
          child: const Icon(
            Icons.arrow_back_ios,
            color: Colors.black54,
          ),
        ),
      ),
      body: ListView.builder(
        itemCount: list_s.length,
        itemBuilder: (context, index) {
          return ListTile(
            title: Row(
              children: <Widget>[
                Icon(Icons.person),
                Expanded(
                  child: Text("${list_s[index].name} (${list_s[index].email})"),
                )
              ],
            ),
            subtitle: Row(
              children: <Widget>[
                Icon(Icons.message),
                Expanded(
                  child: Text(list_s[index].feedback.toString()),
                )
              ],
            ),
          );
        },
      ),
    );
  }
}

이 문제를 해결하기 위해 제가 한 일은 다음과 같습니다.

List<YourItemClass> items = [];

final data = jsonDecode(resp.body); //Here it goes your json array

for (dynamic item in data) {
    items.add(YourItemClass.fromMap(item));
}

return items;

물론, 당신은 그것을 가질 필요가 있다.fromMap()에 있어서의 방법.YourItemClass그렇지 않으면 quicktype.io에서 클래스의 단일 json 인스턴스를 붙여넣을 수 있습니다(및 dart 언어를 선택합니다).

언급URL : https://stackoverflow.com/questions/51053954/how-to-deserialize-a-list-of-objects-from-json-in-flutter

반응형