jsonflutterdartwebsocketmongo-dart

Error: Expected a value of type 'String', but got one of type '_MapStream<dynamic, Iterable<Post>>'


I have wrote the following code on server.

server code:

import 'dart:convert';
import 'package:mongo_dart/mongo_dart.dart';
import 'package:shelf/shelf.dart';
import 'package:shelf_web_socket/shelf_web_socket.dart';
import 'package:web_socket_channel/web_socket_channel.dart';

class PostsSocketApi {
  PostsSocketApi(this.store);
  final List<WebSocketChannel> _sockets = [];
  final DbCollection store;
  Handler get router {
    return webSocketHandler((WebSocketChannel socket) {
      socket.stream.listen((message) async {
        final data = json.decode(message);
        print(data);
                if (data['action'] == 'LOGIN') {
          final user = await store.findOne(
              where.eq('name', data['name']).eq('password', data['password']));
          if (user != null) {
            for (final ws in _sockets) {
              ws.sink.add(json.encode('name'));
// probably there must be .toString()       ^^^             
            }
          }
          if (user == null) {
            for (final ws in _sockets) {
              ws.sink.addError('NOSUCHUSER');
            }
          }
        }
      });
      _sockets.add(socket);
    });
  }
}

And now I want to get the 'name' field into my variable tmp_name to compare it with name on login field, like that:

login code:

  void loginUser() async {
    final name = emailController.text;
    final password = passwordController.text;
    widget.api.send(
        json.encode({'action': 'LOGIN', 'name': name, 'password': password}));
    String tmp_name = widget.api.getName;
// method from API               ^^^^^^^
    if (tmp_name == name) {
      SharedPreferences prefs = await SharedPreferences.getInstance();
      setState(() {
        prefs.setString('name', name);
      });

      Navigator.of(context)
          .pushReplacement(MaterialPageRoute(builder: (context) => Home()));
    } else {
      print('error: no such user');
    }
  }

API code in App:

class PostsSocketApi {
  PostsSocketApi()
      : _api = WebSocketChannel.connect(
            Uri.parse('ws://localhost:8082/posts-ws/'));

  final WebSocketChannel _api;

  Stream<List<Post>> get stream => _api.stream.map<List<Post>>((data) {
        final decoded = json.decode(data);
        return (decoded as List)
            .map<Post>(
              (json) => Post.fromJson(json),
            )
            .toList();
      });

  ValueChanged<String> get send => _api.sink.add;

  get getName => _api.stream.map((data) {
        final decoded = json.decode(data['name']);
        return (decoded as List).map<Post>(
          (json) => Post.fromJson(json),
        );
      });
}

However, I got the following error in APP code and don't know how to solve it.

Error: Expected a value of type 'String', but got one of type '_MapStream<dynamic, Iterable<Post>>'

Server code works fine (compare data and print if it's wrong user)

Server response on register:

{action: ADDUSER, name: 6, password: 6, id: 6}

Server response on login as existing user:

{action: LOGIN, name: 6, password: 6}

Server response on login as NOT-existing user:

{action: LOGIN, name: fqfqfq, password: qfqfqfq}
NOSUCHUSER
ERROR - 2022-03-21 11:55:27.183011
Asynchronous error
type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'String'
PostsSocketApi.router.<fn>.<fn>
package:io/api/socket_api.dart:79

For Ruchit:

userID type is String. If I write like that, the same error thrown.

  get getName => _api.stream.map((data) {
        final decoded = json.decode(data['name']);
        return (decoded as List)
            .map<String>((json) => Post.fromJson(json).userID);
      });

But, if I write like that, I get the type error: error: The return type 'String' isn't a 'Post', as required by the closure's context.

Code:

  get getName => _api.stream.map((data) {
        final decoded = json.decode(data['name']);
        return (decoded as List)
            .map<Post>((json) => Post.fromJson(json).userID );
      });

Any ideas? (Even about refactoring other code)

I'm tried to find some explanations in documentation, but... Write if u need some more code or explanations. Or if you can give me advice about how to make login by another way - tell me.

Please help me if you can <3


Solution

  • Here you are returning whole post object and you are getting as String which mismatches thus it is showing error.

    get getName => _api.stream.map((data) {
            final decoded = json.decode(data['name']);
            return (decoded as List).map<Post>(
              (json) => Post.fromJson(json).field,  //here field is the field you want from Post object and you are getting string so this field should have type string.
               //eg. Post.fromJson(json).name
            );
          });