Parse Server SDK - Include Object method doesn't work for fetching the whole object in flutter - flutter

I was using parse server sdk in my app for database.
I have three class in my Back4App Dashboard which are "_User", "Office", "Office_Members".
In Office_Members class it has following columns,
user_id (Pointer to _User)
office_id (Pointer to Office)
count
To fetch the data including Pointer to _User as well from Office_Members, I am using following code,
QueryBuilder<ParseObject> parseQuery = QueryBuilder<ParseObject>(ParseObject("Office_Members"))
..whereEqualTo("office_id", ParseResponse_OfficeObject)
..includeObject(["user_id "]);
ParseResponse apiResponse = await parseQuery.query();
Output :
Payload : [{"className":"Office_Members","objectId":"twpDY51PUK","createdAt":"2020-08-14T09:58:59.775Z","updatedAt":"2020-08-14T09:58:59.775Z","office_id":{"__type":"Pointer","className":"Office","objectId":"4dkfSMrwBI"},"user_id":{"__type":"Pointer","className":"_User","objectId":"Hx5xJ5ABxG"},"count":1}]
In my payload response i am not getting whole user_id pointer response.
So can anybody help me that what i might be doing wrong?
Thanks.

The data should be included.
The logging function simply does not print the data of pointers.

The data should be included. The print function not print the data of pointers.
You can print it out directly for testing purposes, E.g.
response.results[0].get('user_id').get('name')
Evaluation Expression E.g.
In your model u can access at same way, E.g
Call Model
if(response.success){
return response.results.map((p) => Example.fromParse(p)).toList();
} else {
throw ParseErrors.getDescription(response.error.code);
}
Model
import 'package:parse_server_sdk/parse_server_sdk.dart';
class Example {
Example({this.id, this.name});
Example.fromParse(ParseObject parseObject) :
id = parseObject.objectId,
name = parseObject.get('user_id').get('name');
final String id;
final String name ;
#override
String toString() {
return 'Example{id: $id, name: $name}';
}
}

Why not simply use cloud code ? I'm not to familiar with flutter but I can suggest you this alternative solution.
Write a function like this.
Parse.Cloud.define("fetchMemberAndUser", async (request) => {
//Pass in ParseResponse_OfficeObject ID as parameter
var objectId = request.params.id;
//Now do a simple get query
var query = new Parse.Query(Parse.Object.extend("Office_Members"));
//Using .includes to get the user profile object
query.include("user_id");
//This will return Office_Memebers Object along with user profile
return query.get(objectId,{useMasterKey:true});
}

Related

appwrite list users search params

I am trying to use appwrite server sdk list users to get userid from an email.
The documentation says there is a search: option that can be used but no where does it say what the format of that String? is.
What is the format of the search: String? to only get a list of users whose email matches?
void main() { // Init SDK
Client client = Client();
Users users = Users(client);
client
.setEndpoint(endPoint) // Your API Endpoint
.setProject(projectID) // Your project ID
.setKey(apiKey) // Your secret API key
;
Future result = users.list(search: '<<<WHAT GOES HERE>>>');
}
:wave: Hello!
Thanks for bringing this question up, this is definitely not well documented, I'll note this down and try to make it clearer in the docs, but here's how you'd approach this in Dart:
final res = users.list(search: Query.equal('email',
'email#example.com'));
res.then((response) {
print(response.users[0].toMap());
}).catchError((error) {
print(error);
});
The Query object generates a query string, and works similar to how listDocument would work. The difference here is that it only takes a single query string instead of a list.

Casting an object in Flutter/Dart returns _HashSet

I am having some problem in Flutter with casting a dynamic to a custom object. I receive JSON as response from a web service, which I store as an instance of my object in a class as dynamic together with some other meta information. When I try to cast that object to my desired class (e.g. LoginReply) I keep getting the following error message: Expected a value of type 'LoginReply', but got one of type '_HashSet<LoginReply>'
Here is my response class that stores the reply object:
class DioResponse {
String? error;
dynamic object;
DioResponse(this.error, this.object);
bool get isSuccessful => error == null || error!.isEmpty;
T get<T extends dynamic>() {
print("Object: $object");
return object.cast<T>();
}
}
I serialize the JSON response like this:
LoginReply _serializeResponse(Map<String, dynamic> json) {
LoginReply reply = LoginReply.fromJson(json);
if (!reply.header!.successful) {
errorMessage.value = "${reply.header!.errorCode}: ${reply.header!.errorMessage}";
return LoginReply();
}
AppConfig.persistString("token", reply.token!);
return reply;
}
And here is how I try to access the DioReponse.object / LoginReply:
DioResponse response = await handler.post(Globals.nodeAddress, ......);
if (response.isSuccessful) {
//LoginReply reply = response.get<LoginReply>();
print("Object: ${response.object}");
LoginReply reply = response.object as LoginReply;
The print output on the second last line prints: Object: {Instance of 'LoginReply'} which makes the whole error even harder to understand for me.
The problem was in the closure that was passed as parameter to the post function. So it really returned a Set. I pass a function to the DioHandler class that is called there and then it just works the way it should.

How to parse an object variable in eventChannel callback method?

I am programming a flutter app, in which I have a callback from the native system containing some nfc information. I register the callback via the following line of code:
eventChannel.receiveBroadcastStream().listen(_onEvent, onError: _onError);
The callback looks like this:
void _onEvent(Object event) {
//Receive Event
print("NFC Event received");
//Get the Payload
event['Payload']; //This does not work, it gives an error
}
But how can I parse out the data? I know it contains a field by the name Payload however, I cannot access it via event['Payload'].
I am very confused, I tried to cast it to another type like this: Map<String, String> eventMap = Map<String, String>.from(event); but that didnt work. Could someone please point out what I am doing wrong and how I can correctly extract the data?
Without too much information of native part, I suggest
you can reference this package or fork this https://github.com/akeblom/flutter-nfc-reader
directly
this repo fix some issue of pub.dev and work well in real device
the dart code you need reside in
https://github.com/akeblom/flutter-nfc-reader/blob/master/lib/flutter_nfc_reader.dart
void _onEvent(dynamic data) {
print("Event");
print(data);
}
Edit add more detail
akeblom has add Write NFC capability to IOS, so IOS part should work. please ue this fork https://github.com/akeblom/flutter-nfc-reader
For IOS MissingPluginException issue, I do not have IOS, I suggest you can ask akeblom
The data part you mentioned in comments if I do not misunderstand is line 77, please see describe below
In Android part.
https://github.com/akeblom/flutter-nfc-reader/blob/master/android/src/main/kotlin/it/matteocrippa/flutternfcreader/FlutterNfcReaderPlugin.kt
line 174, use kotlin mapOf returns a new read-only map with the specified contents and eventSink.success result to Dart
if (message != null) {
val data = mapOf(kId to id, kContent to message, kError to "", kStatus to "read")
eventSink?.success(data)
}
In https://github.com/akeblom/flutter-nfc-reader/blob/master/lib/flutter_nfc_reader.dart
line 22, with named constructor
factory NfcData.fromMap(Map data) {
NfcData result = NfcData(
id: data['nfcId'],
content: data['nfcContent'],
error: data['nfcError'],
statusMapper: data['nfcStatus'],
);
In line 77, NFC read start and _onEvent(dynamic data) get the data.
stream use this named constructor, and parse data, here with map((result)) transfer to NfcData
static Stream<NfcData> get read {
final resultStream = _channel
.invokeMethod('NfcRead')
.asStream()
.asyncExpand((_) => stream
.receiveBroadcastStream()
.map((result) => NfcData.fromMap(result)));
return resultStream;
In https://github.com/akeblom/flutter-nfc-reader/blob/master/example/lib/main.dart
line 33, response has transfered to NfCData, so example just use _nfcData = response;
FlutterNfcReader.read.listen((response) {
setState(() {
_nfcData = response;
});
});
The simplest way I found to parse an event to a Map is the following:
I encoded the variable to a String (but I use json.encode(event)instead of event.toString()as encode(event)returns a valid string.
Then I use this string to construct a map via json.decode. All of this is achieved with the flutter native library dart:convert. The complete code looks like this:
import 'dart:convert';
...
void _onEvent(dynamic event) {
//Receive Event
print("NFC Event received");
String str = json.encode(event);
Map eventMap = json.decode(str);
}
Have you tried event.toString()? It might return a string containing the field you are trying to get, from which you can easily parse the value.
You may also want to try:
Class<?> clazz = event.getClass();
Field payload= clazz.getField("Payload"); //Note, this can throw an exception if the field doesn't exist.
String fieldValue = payload.toString();
If it isn't returning what you want, you may need to make an interface for the object type, with a get method, or override the toString method to get return the Payload value.

Modify SingleResult<T> from TableController in Azure Mobile Services before returning it to the client?

I am using Azure Mobile Services. I have a TableController<Photo>. In the controller, I can retrieve a single photo by id successfully. No problems using the following method:
//works
public SingleResult<Photo> GetPhoto(string id)
{
return Lookup(id);
}
However, since the photo is stored in Azure storage as a private blob, I want to tack on the SAS (Shared access signature) to allow my mobile client direct read access to the Azure blob for a given period of time.
In the GetPhoto call, I am successfully retrieving the SAS using the CloudBlobClient (removed for brevity).
I have defined a property on Photo called SasQueryString. I want to set it on the <Photo> object retrieved using Lookup(id) but the data returned from Lookup(id) is an IQueryable, not my strongly typed Photo object.
//! INCORRECT ! -- because photoResult is IQueryable
public SingleResult<Photo> GetPhoto(string id)
{
SingleResult<Photo> photoResult = Lookup(id);
//SingleResult<Photo> does not contain SasQueryString
photoResult.SasQueryString = "SAS from CloudBlobClient";
return photoResult;
}
If I do this, I can set the SasQueryString:
Photo photoResult = (Photo)Lookup(id).Queryable.FirstOrDefault<Photo>();
photoResult.SasQueryString = "SAS from CloudBlobClient";
However, I'm not sure how to return this strongly typed object as a SingleResult<Photo>.
//! INCORRECT ! -- this doesn't work because the Create method expects an IQueryable
return SingleResult<Photo>.Create(photoResult);
I've also tried this but photoResult is anIQueryable so I can't set the strongly typed SasQueryString value this way either.
//! INCORRECT !
var photoResult = Lookup(id).Queryable.Select(x => new Photo()
{
Id = x.Id,
TheOtherFields = x.TheOtherFields
});
photoResult.SasQueryString = "SAS from CloudBlobClient";
I am obviously missing something crucial here but it seems like I should be able to combine the lookup for the photo and the request for the SAS into a single call that returns my photo data after tacking on the SAS ticket...
== UPDATE ==
I found the following example: Creating a Leaderboard App with Azure Mobile Services .NET Backend. It is doing something similar to what I want to do but I have yet to try it.
// GET tables/PlayerRank/48D68C86-6EA6-4C25-AA33-223FC9A27959
public SingleResult<PlayerRankDto> GetPlayerRank(string id)
{
var result = Lookup(id).Queryable.Select(x => new PlayerRankDto()
{
Id = x.Id,
PlayerName = x.Player.Name,
Score = x.Score,
Rank = x.Rank
});
return SingleResult<PlayerRankDto>.Create(result);
}
which modified for my situation might look like the following:
public SingleResult<Photo> GetPhoto(string id)
{
var result = Lookup(id).Queryable.Select(x => new Photo()
{
Id = x.Id,
ImageUri = x.ImageUri,
SasQueryString = GetSas(id),
});
return SingleResult<PlayerRankDto>.Create(result);
}
You are not doing it the right way:
When you get the a list of Photos or a Photo it will give the data from storage in database and SasQueryString is not storaged, only the Url from blob storage should be;
You only provide SasQueryString in Insert or Update methods, because you need to define the url or update the url if need;
Note: Get methods do not change data
When a client app insert a photo the backend should do:
create the url for the photo and generate the SasQueryString
save the photo, with the url create, in database
before return the photo set the SasQueryString
client app upload the image to blob using the SasQueryString and url you provided
Why you have a Photo and a Controller for Photo???
If you have an object "Car" that has an image, it should have "car.Url" and a class similar to BlobItem.cs and you can see BlobStorageExtensions.cs.
Note: BlobItem.cs will be a not mapped property, I do not want save it on database.
I need to create a sample with it and the nugets...

Not able to update data of ParseUser class in Unity3D using Javascript

I am using this code to update data of a Parse User, but the data is not updating nor am I able to retrieve the data.
I am able to do update and retrieve the data for a ParseObject class created by me. Can someone tell me where I am wrong on this?
Out of all the debugs I have set I am able to see only the 1st debug "parse GetSync function passed" and the rest are not printing.
var parseUser: ParseUser;
function FBtoParse(){
var query = ParseUser.Query;
query.GetAsync("Q0D9eBvRee").ContinueWith(GetSync);
Debug.Log("parse GetSync function passed");
Debug.Log("Object ID: "+ parseUser["objectId"]);
Debug.Log("username is : "+ parseUser["username"]);
Debug.Log("User Updated");
}
var GetSync = function (t:System.Threading.Tasks.Task.<ParseUser>){
parseUser = t.Result;
};
function OnGUI{
if (GUILayout.Button("Parse"))
{
FBtoParse();
Debug.Log("Pressed Parse");
}
}
Parse at the moment only allows ParseUsers to update their own object through authentication.
https://parse.com/docs/js/guide#users-security-for-user-objects