Home > Blockchain >  Dart/Flutter: Json to class mapping is not working
Dart/Flutter: Json to class mapping is not working

Time:01-16

I have a FutureBuilder that has no Data. I have this Function to get the Data from the Backend:

Future<List<OrderReceipt>> getOrderReceipt(orderno) async {
  final response = await HttpService.order_receipt(orderno);
  var decoded = json.decode(response.body)["qry"].cast<Map<String,dynamic>>();
  print(decoded);
  var OrderR = await decoded.map<OrderReceipt>((json) => OrderReceipt.fromJson(json)).toList();
  return OrderR;
}

This is the class with the mapping function:

class OrderReceipt {
  final String LUKEBLART;
  final String LUKEBLOART;
  final String LUKEBLONR;
  final String LUKEBLVC;
  final String LUKEBLBNR;
  final String LUKEBLDRAKT;
  final String LUKEBLADS;
  final String LUKEBLDATUM;
  final String LUKEBLPGM;
  final String LUKETIME;
  final String LUKESART;
  final String LUKEPAGE;
  final String LUKELINE;
  final String LUKELNR;
  final String LUKETXT;

  OrderReceipt({
    required this.LUKEBLART,
    required this.LUKEBLOART,
    required this.LUKEBLONR,
    required this.LUKEBLVC,
    required this.LUKEBLBNR,
    required this.LUKEBLDRAKT,
    required this.LUKEBLADS,
    required this.LUKEBLDATUM,
    required this.LUKEBLPGM,
    required this.LUKETIME,
    required this.LUKESART,
    required this.LUKEPAGE,
    required this.LUKELINE,
    required this.LUKELNR,
    required this.LUKETXT,
  });

  factory OrderReceipt.fromJson(Map<String, dynamic> json) {
    return OrderReceipt(
        LUKEBLART: json['LUKEBLART'] as String ?? '', 
        LUKEBLOART: json['LUKEBLOART'] as String ?? '',   
        LUKEBLONR: json['LUKEBLONR'] as String ?? '',  
        LUKEBLVC: json['LUKEBLVC'] as String ?? '', 
        LUKEBLBNR: json['LUKEBLBNR'] as String ?? '', 
        LUKEBLDRAKT: json['LUKEBLDRAKT'] as String ?? '', 
        LUKEBLADS: json['LUKEBLADS'] as String ?? '', 
        LUKEBLDATUM: json['LUKEBLDATUM'] as String ?? '',  
        LUKEBLPGM: json['LUKEBLPGM'] as String ?? '',
        LUKETIME: json['LUKETIME'] as String ?? '',
        LUKESART: json['LUKESART'] as String ?? '', 
        LUKEPAGE: json['LUKEPAGE'] as String ?? '', 
        LUKELINE: json['LUKELINE'] as String ?? '', 
        LUKELNR: json['LUKELNR'] as String ?? '', 
        LUKETXT: json['LUKETX'] as String ?? '', 
    );}
}

And here is a example of the json (only one dataset):

[{LUKEBLADS: 222222, LUKEBLART: W , LUKEBLBNR: 333333, LUKEBLDATUM: 20230113, LUKEBLDRAKT: FX  , LUKEBLOART: FX  , LUKEBLONR: 4444, LUKEBLPGM: XXXKG    , LUKEBLVC: X1 , LUKELINE: 41, LUKELNR: 36, LUKEPAGE: 1, LUKESART: 1, LUKETIME: Fri, 13 Jan 2023 09:54:02 GMT, LUKETXT:                                    ExampleText                                      USD         66,20                                                                                          },]

There are a lot of spaces in LUKETXT, because I am generating a .pdf with monospace font (Just for good sizing from the AS400 Database I am working with)

The problem ist in the getOrderReceipt(orderno) Future, the future prints the decoded but did not return anything from await decoded.map<OrderReceipt>((json) => OrderReceipt.fromJson(json)).toList();.

I dont get any error - the FutureBuilder that builds the Future<List<OrderReceipt>> is processing for like two seconds and then there is no data. I have two other FutureBuilders in my Project and dont have any problems with them. Does anybody know the error?

Thanks..

EDIT 1:

@Jozott, @Eric Martin and @pmatatias: I have updated the FutureFunction and removed the .cast<Map<String,dynamic>>() and also the await but nothing changes in the execution - the error is still there and the function ends by not returning anything from decoded.map<OrderReceipt>((json) => OrderReceipt.fromJson(json)).toList(); - my updated function:

Future<List<OrderReceipt>> getOrderReceipt(orderno) async {
  final response = await HttpService.order_receipt(orderno);
  print(response);
  var decoded = json.decode(response.body)["qry"];
  var OrderR = decoded.map<OrderReceipt>((json) => OrderReceipt.fromJson(json)).toList();
  print(OrderReceipt);
  return OrderR;
}

I also tried to change the factory function to:

...
...
  factory OrderReceipt.fromJson(json) {
    return OrderReceipt(
          ...
          ...
      ); }
...
...

EDIT 2: This is as talked in the comments the FutureFunction with the try-catch-Block:

Future<List<OrderReceipt>> getOrderReceipt(orderno) async {
  try {
    final response = await HttpService.order_receipt(orderno);
    print(response);
    var decoded = json.decode(response.body)["qry"];
    var OrderR = decoded.map<OrderReceipt>((json) =>
        OrderReceipt.fromJson(json)).toList();
    return OrderR;
  } catch(err) {
    print('Caught error: $err');
    throw 'Caught error: $err';
  }
}

The following Error is displayed:

type 'null' is not a subtype of type 'string' in type cast

And I also tried to comment out the "LUKETXT" in the Modell - and then it works. Maybe this error can be thrown because there can be dots, colons and other special caracters in the value? -> But as I see in the devtools these special caracters are correctly decoded in the json.decode function to each of them headers and remain a String.

CodePudding user response:

You made a typo in a name field. LUKETX instead of LUKETXT

In your factory :

        LUKETXT: json['LUKETX'] as String ?? '',

Your code try to cast null value to a string. That's why you get this error.

As @jozott mentionned, you can use a code generator code like json_serializable to avoid typos : https://pub.dev/packages/json_serializable

By the way, i don't think you have to declare the cast "as string" because dart infers the type. Imagine a String field name, you can write this :

 User.fromJson(Map<String, dynamic> json)
      : name = json['name'] ?? ''
  • Related