Dart:Convert nested object to Map with json_annotaion - dart

import 'package:json_annotation/json_annotation.dart';
part 'soul_chat_videoparty_avatar.g.dart';
#JsonSerializable()
class VideoPartyAvatarCategory {
VideoPartyAvatarCategory();
List<VideoPartyAvatar>? avatarResourceList;
factory VideoPartyAvatarCategory.fromJson(Map<String, dynamic> json) =>
_$VideoPartyAvatarCategoryFromJson(json);
Map<String, dynamic> toJson() => _$VideoPartyAvatarCategoryToJson(this);
}
#JsonSerializable()
class VideoPartyAvatar {
VideoPartyAvatar();
factory VideoPartyAvatar.fromJson(Map<String, dynamic> json) =>
_$VideoPartyAvatarFromJson(json);
Map<String, dynamic> toJson() => _$VideoPartyAvatarToJson(this);
}
My data structure is like above.A category has a list with a specific type.So I use json_annotion to convert data after I fetch it from my server.After that I try to send it back to my server.So I use the method VideoPartyAvatarCategory.toJson to convert it to a map to send.Although the category is converted to a map,the list still contains this specific type,not a map.
It can't be a map apparently because the convert code is like this in .g.dart file.
Map<String, dynamic> _$VideoPartyAvatarCategoryToJson(
VideoPartyAvatarCategory instance) =>
<String, dynamic>{
'avatarResourceList': instance.avatarResourceList,
};
So is there a way to convert a nested object to a Map totally?I tried using decode or encode method,convert it to String then to a Map,it can approach,which isn't perfect.

Related

Is there any way to customise serialization keys for classes conditionally?

I'm new to flutter and I need to implement custom serialization that reads the json object.
My class is :
#JsonSerializable()
class Activity {
#JsonKey(name: 'ActivityId')
int activityId = 0;
#JsonKey(name: 'ActivityType')
int type = 0;
#JsonKey(name: 'Title')
String name;
Map<String, dynamic> json) =>
_$SFActivityAnswerQuestionAnswerPostFromJson(json);
Map<String, dynamic> toJson() =>
_$SFActivityAnswerQuestionAnswerPostToJson(this);
The problem is the keys in the API response for Title can change depend on the type of request and it can be Name.
My question is is there any way to add support to check the request and change #JsonKey(name: 'Title') to #JsonKey(name: 'Name') ?

Flutter Firestore add new document with Custom ID

How to add new document with custom id using Dart and Flutter?
PS: I can add new document to collection but its id sets randomly, using this code
postRef.add(data);
which postRef is CollectionReference and data is Map<String, dynamic>
You can use set() function instead of add().
Here's full code:
final CollectionReference postsRef = Firestore.instance.collection('/posts');
var postID = 1;
Post post = new Post(postID, "title", "content");
Map<String, dynamic> postData = post.toJson();
await postsRef.doc(postID).set(postData);
I hope that help anyone.
Update 2021:
Instead of using add, use set on the document.
var collection = FirebaseFirestore.instance.collection('collection');
collection
.doc('doc_id') // <-- Document ID
.set({'age': 20}) // <-- Your data
.then((_) => print('Added'))
.catchError((error) => print('Add failed: $error'));
String uniqueCode = //Your Unique Code
DocumentReference reference = Firestore.instance.document("test/" + uniqueCode );
//Setting Data
Map<String, String> yourData;
reference.setData(yourData);
You can try this code to insert new Document with customID
DocumentReference<Map<String, dynamic>> users = FirebaseFirestore
.instance
.collection('/users')
.doc("MyCustomID");
var myJSONObj = {
"FirstName": "John",
"LastName": "Doe",
};
users
.set(myJSONObj)
.then((value) => print("User with CustomID added"))
.catchError((error) => print("Failed to add user: $error"));

How to get entity manager in form type

How could I get entity manager when building forms?
I would like to search results from the database and build the choices for choicetype.
I know I could use entitytype instead but in this situation I want to record string in database than an object.
And also I need to add some more options as well.
Thank you.
In Symfony 3.2 (and possibly others, I'm not sure about 3.1, but it is probably the same), the $this->createForm() method needs a string as the first parameter, and cannot take a form object.
Add a configureOptions method to your form class:
class YourFormType extends AbstractType
{
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'entityManager' => null,
]);
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
// Entity Manager is set in: $options['entityManager']
}
}
Then get the form in your controller like so, passing in the Entity Manager:
$form = $this->createForm(
YourFormType::class,
$yourEntity,
[
'entityManager' => $this->getDoctrine()->getManager(),
]
);

jQuery Autocomplete and WebApi Sorting

I am using a WebApi controller to return an IDictionary to jQuery autocomplete like so:
public IDictionary<int, string> GetClientAuto(string term)
{
var clients = db.Clients.Where(n => n.Name.Contains(term)).OrderBy(n => n.Name);
return clients.ToDictionary(n => n.ClientID, n => n.Name);
}
The issue is although I add a breakpoint and check the variable clients is sorting by Name turns to to be true, the order shown in the autocomplete box is different, possibly I expect by the ID. I tried adding this to the autocomplete: sortResults:false, but with no effect.
I have this in my succes function, is there something here maybe I need to change for the order to work on the label i.e. Name:
success: function (json) {
// call autocomplete callback method with results
response($.map(json, function (name, val) {
return {
label: name,
value: val
}
}));
},
Its being sorted by the ToDictionary call, the order of dictionaries isn't actually defined (http://msdn.microsoft.com/en-us/library/yt2fy5zk.aspx) as it shouldn't matter, however i believe it is typically the value of the key, not the value.
You could resort it in javascript to be by name, or you could return something other than a dictionary from your api. Either a IEnumerable> or IEnumerable would do the trick.
Alterntively look into the OrderBy methods on the dictionary, however they all appear to return a list of KeyValuePairs.
End result should look something like
public IEnumerable<KeyValuePair<int, string>> GetClientAuto(string term)
{
return db.Clients.Where(n => n.Name.Contains(term)).OrderBy(n => n.Name).Select(n => new KeyValuePair<int, string>(n.ClientID, n.Name ));
}
success: function (json)
{
response($.map(json, function (item) {
return {
label: item.Value,
value: item.Key
}
}));
},

When using Symfony2.1 forms, at what point should I bind custom data (an object) based on form values to my form's object?

Given the following scenario, where should I put logic to bind Department to Review:
Entities:
Dealership (has many departments)
Department (has one type)
DepartmentType
Review (has one dealership and one department)
On my ReviewForm I need the user to be able to select a Dealership and a DepartmentType, and then in some form of callback or pre/post bind, work out from them which Department to bind to the Review.
I also need this to happen prior to validation so that I can validate that the Department is child of the Dealership.
Note: Review relates to both Dealership and Department when it could just relate to Department to ease traversal and other logic I have going on.
There are two approaches I've tried so far but reached deadends / confusion.
DataTransformer on the DepartmentType on the form, not sure I understand this properly, my transform / reverseTransform methods were getting passed in the Review object, not the field object.
PRE_BIND, happens before validation but I only have raw data to work with, no objects
POST_BIND, happens after validation :(
For the final step of validation of the relationship I have a relatively simple validator that should do the job, but I'm not sure at what point I am meant to bind data to the object like this. Any pointers?
As validation is also done in a POST_BIND listener, you could simply add your POST_BIND listener with a higher priority than the validation listener (i.e. anything > 0).
If you're writing a listener:
$builder->addEventListener(FormEvents::POST_BIND, $myListener, 10);
and if you're writing a subscriber:
public static function getSubscribedEvents()
{
return array(
FormEvents::POST_BIND => array('postBind', 10),
);
}
public function postBind(FormEvent $event)
{
...
}
I would go with a standard (ie: non-Doctrine) choice type containing a choice to represent each DepartmentType.
Then use a DataTransformer to turn the selected option into the relevant type, and vice versa.
Your custom FormType should end up looking something like this:
class Department extends AbstractType
{
private $em;
public function __construct(EntityManager $em) {
$this->em = $em;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$transformer = new DepartmentToTypeTransformer($this->em);
$builder->addViewTransformer($transformer, true);
$builder->getParent()->addEventListener(FormEvents::PRE_BIND, function($event) use ($transformer) {
$data = (object) $event->getData();
$transformer->setDealership($data->dealership);
});
}
public function getParent()
{
return 'choice';
}
public function getName()
{
return 'department';
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$choices = array();
foreach ($this->em->getRepository('AcmeDemoBundle:DepartmentType')->findAll() as $type) {
$choices[$type->getId()] = (string) $type;
}
$resolver->setDefaults(array(
'choices' => $choices,
'expanded' => true
));
}
}
Note the passing of the Dealership into the DataTransformer for use in the transformation.
And DataTransformer something like this:
class DepartmentToTypeTransformer implements DataTransformerInterface
{
private $em;
private $dealership;
public function __construct($em)
{
$this->em = $em;
}
public function transform($department)
{
if (null === $department) {
return $department;
}
return $department->getType()->getId();
}
public function reverseTransform($type)
{
if (null === $type) {
return $type;
}
return $this->em->getRepository('AcmeDemoBundle:Department')->findOneBy(array(
'dealership' => $this->getDealership(),
'type' => $type
));
}
public function getDealership() {
return $this->dealership;
}
public function setDealership($dealership) {
$this->dealership = $dealership;
return $this;
}
}
Your confusion regarding what is being passed to your transformer is most likely caused by the transformer you're binding being appended to pre-existing behaviour, try adding true as the second parameter to addViewTransformer:
$transformer = new DepartmentToTypeTransformer($this->em);
$builder->addViewTransformer($transformer, true);
From the docs:
FormBuilder::addViewTransformer(
DataTransformerInterface $viewTransformer,
Boolean $forcePrepend = false
)
Appends / prepends a transformer to the view transformer chain.

Resources