Encoding a nested object that does not have nested property in its model - ios

Say I have the following struct:
struct Event: Codable {
var id: Int
.... // many non nested fields
}
In my application a user is allowed to create a list of events. Once the user is finished I'd like to pass that list to my server via a POST request.
In order to do so I need to create a valid JSON object that looks like this.
This is a list of Event with a leading key of "events".
{ "events": [{"id": 1, ... more of the non nested fields ... },{ ... }]}
How can I setup my Event object in such a way that JSONEncoder.encode(events) will return the expected JSON above? I would really like to avoid having a CodingKey for each field because they encode,decode just fine expect in this circumstance. I'd also like to avoid nesting this Event object inside another struct called Events to get the desired result.

You can just encode a dictionary which associates your events array to the key "events"
JSONEncoder.encode(["events": events])

Related

what was first: view or serializer?

Lately i've face problem of nested objects posting. After researched the proper solution involving either views create() implementation or separate serializers for reading and writing with create() method overriten.
I post with axios, and my object looks like this:
{
comment: str
priority: str
file: int // -> this one is ForeignKey for another object and needs its PK which is ID
}
The way i want to have my post data structured is:
{
comment: str
priority: str
file: str // -> which is file object name
}
After sending this request DRF should look in db for file on this name and place its id in this filed.
Is this the proper way ? Or should i nest whole object instead of just its id ?
Another question, offtopic: what is called first after request: serializer or view ?
You can use SlugRelatedField in your serializer
file = serializers.SlugRelatedField(
slug_field='name'
)
But name field of your model should be unique=True

Jersey multiple POST methods with same path

I am trying to make two types of POST methods, both of which create objects and populate a database.
Method 1 adds a single object to the database.
Method 2 adds an array of objects to the database.
// Create new agent status
#POST
#Consumes(MediaType.APPLICATION_JSON)
public Response createAgentStatus(#Context HttpServletRequest request, AgentStatus agentStatus) {
...
}
// Create multiple agent statuses at once
#POST
#Consumes(MediaType.APPLICATION_JSON)
public Response createAgentStatuses(#Context HttpServletRequest request, Collection<AgentStatus> agentStatuses) {
...
}
I am getting an error, as expected, because Jersey cannot tell the difference between the two paths. Both POSTS are treated the same to Jersey, so it cannot tell which one to route which to based on my input.
How can I make it so that Jersey can detect the format of my input and route accordingly? Thank you
Ex:
Method 1 JSON input (createAgentStatus) :
{
"agentId":"A123456",
"agentStatus":"NOTREADY",
"timeStamp":"2015-10-08T13:37:32:235Z",
"reason":"Break",
"reasonCode":"100"
}
Method 2 JSON input (createAgentStatuses) :
[
{
"agentId":"A123456",
"agentStatus":"NOTREADY",
"timeStamp":"2015-10-08T13:37:32:235Z",
"reason":"Break",
"reasonCode":"100"
},
{
"agentId":"B654321",
"agentStatus":"AVAIL",
"timeStamp":"2015-10-08T13:37:32:235Z",
"reason":"Call",
"reasonCode":"200"
}
]
Maybe you could use a #QueryParam to determine which option the endpoint needs and call the appropiate method, something like "batch=true" or you could have a path "/batch" to insert multiple records.
I think a single endpoint is enough to achieve this. If we pass in a list of objects it should create objects based on the size of the list.
In the backend, you can traverse through the list to add the objects to the database. A single object gets created if the request list has only one object and multiple gets created if it has multiple objects.

Grails binding one to one associations

When you generate grails views, grails looks at your relationships and generates the right html for your form data to be automatically binded to the back end domain. For one to one associations grails creates a drop down list.
However, you might not want to present that property as a drop down list but something more custom (for example a text field with autocomplete). As soon as you do that the value that comes to the controller from that field, comes in as a String and you have to first:
Clear errors
Perform a findBy based on a given param and assign it to the property of the domain
I really want to avoid doing findBys in the controller as much as possible because it seems like I am doing logic/things that should not go there. The controller should delegate to the Service layer. It is not clear to me from the grails documentation how would I do that by using bindData which seems to work really well with String, date, Integer properties etc.. but I do not see how bindData is used for properties that are other domains.
I also really want to avoid passing the params object to the Service layer as it seems less reusable (or maybe not, correct me if I am wrong). I guess that I do not like how it looks semantically. I would prefer the first over the second:
#Transactional
class WithdrawService {
def addWithdraw(Withdraw withdraw) {
//perform business logic here
}
def createWithdraw(Map params){
//perform business logic here
}
}
Let's take the following example:
class Withdraw {
Person person
Date withdrawDate
}
and the parent lookup table
class Person {
String name
String lastName
static constraints = {
}
#Override
public String toString() {
return "$name $lastName"
}
}
In order for the bind to happen automatically without any extra work grails passes in the following request params to automatically bind the one to one:
person.id
a person map with the id.
[person.id:2, person:[id:2], withdrawDate:date.struct, withdrawDate_month:11, create:Create, withdrawDate_year:2015, withdrawDate_day:10, action:save, format:null, controller:withdraw]
What is the best way to go about this?
Pass two hidden fields that look exactly like this: person.id:2, person:[id:2] that get populated as a result of the Ajax call that populates the autocomplete?
In the controller do a Person.findBySomeKnownProperty(params.someKnownValue)
Or any other approach?

bindData include with nested params

Given the following classes:
Simplified example:
class Query {
Institution institution
}
class Institution {
String name
}
With the following parameters being submitted: query.institution.id=20 and query.institution.name=Example
I would like to include only the institution id and ignore the name from being bound to the query's institution instance.
Is it possible with bindData to explicitly include associated instance's that are nested multiple levels like this?
I haven't seen any examples of this, aside from using the prefix for a single level of nesting, and the following does not seem to work:
Simplified example:
bindData(queryInstance, params, [include: [
'institution.id',
]], 'query')
The best practice is to filter your request parameters through a command object, which can then be used to generate any kind of query.
Command cmd = Command.getInstance()
bindData(cmd, request.params)
if (cmd.validate()) Query query = cmd.generateQuery()
This way you get the benefit of binding only to fields you expose on the command object, while validating and transforming incoming data without involving your domain.

Possible to load entities by string name of entity?

I have the following sample code which gets a list of values from a table in the DB and binds them to a checkbox list.
var db = new DBContext();
db.Entity1.ToList().ForEach(
x => CheckBoxList1.Items.Add(new ListItem(x.Value, x.ID));
I have about 10 checkboxlists like these and I dont want to repeat the code. I'm trying to extract a method out of it and use it for all checkboxes. Is it possible to load an entity by a string name? Something like -
db.Load("Entity1").ToList().ForEach...
So I can pass in the entity name and the checkbox list and do the foreach loop in the method and bind the items, like this -
void BindValues(string entityName, CheckBoxList checkBoxList)
{
db.Load("Entity1").ToList().ForEach(
x => checkBoxList.Items.Add(new ListItem(x.Value, x.ID)));
}
Thank you.
In Code First the DbContext exposes a .Set() or .Set(Type) method to get a handle on the table. So assuming straight EF exposes the same, and you are happy to access your lists by their entity type rather than a string, this would work for you.

Resources