Mirage serializer drop Ids when include and embed some model - serialization

I have a problem with mirage.
I am defining a serializer extending ActiveModelSerializer with serializeIds: 'always', in this case the model is serialized with the relations models ids.
But when i want include some model in the serialized content i use include: ['someModel'], in that case the someModel is included succesfully, but the ids of the rest of relationships are ignored.
How can i include the ids too?

Hm, I believe this is the default behavior. To override this you could call super on the Serializer's serialize method and ensure the ids are added to the payload:
serialize(post, request) {
let json = Serializer.prototype.serialize.apply(this, arguments);
json.post.commentIds = post.commentIds;
return json;
}

Related

python rdflib doesn't export #context and #graph when serializing with json-ld

I have created a Graph() in rdflib 6.2.0 and attempting to export it as JSON-LD. My expectation was that I would end up with a #context containing all the namespace prefixes and a #graph containing all the elements. I'm just simply using:
myGraph.serialize(destination = Path(outputpath), format = "json-ld")
But, I just end up with JSON-LD resembling this kind of structure:
[
{
"#id": "urn:uuid:dccc2ddb-7861-47fc-934c-d2a0901e368e",
"#type": "http://xmlns.com/foaf/0.1/Organization",
},
... (more resources in a flat list)
]
The docs (https://rdflib.readthedocs.io/en/stable/apidocs/rdflib.plugins.serializers.html#rdflib.plugins.serializers.jsonld.JsonLDSerializer) do not really clarify the matter at all, and it is very difficult to find any information on how to export a graph with already existing namespace bindings into a proper JSON-LD with #graph and #context parts.
There exists a Context class in https://rdflib.readthedocs.io/en/stable/apidocs/rdflib.plugins.shared.jsonld.html?highlight=shared.jsonld.context#rdflib.plugins.shared.jsonld.context.Context but without any documentation in the sources, it is very difficult to understand how it should be used. What does the method get_graph() do? Apparently I need to pass a Context instance to the json-ld serializer?
What am I doing wrong?
When it comes to the context, reading the source:
If you set the auto_compact argument to True, the JSON-LD serializer will automatically create a context with all namespace bindings from the graph:
myGraph.serialize(destination = Path(outputpath), format="json-ld", auto_compact=True)
Or alternatively, you can pass the JSON-LD context contents as a dict, and the JSON-LD serializer will internally construct the Context object out of it:
context = {"#vocab": "http://xmlns.com/foaf/0.1/"}
myGraph.serialize(destination = Path(outputpath), format="json-ld", context=context)

SQL-Query returns 'sql-select' string instead of record-set

I'm querying a SQL table via an API and I expect the API to return a <IQueryable> collection of 'Outfit' objects however, the response object is actually just a string containing the sql-select statement.
Questions:
Why is the response object returning the SQL-select statement as a string?
Should the IQueryable<> contain a collection of 'Outfit' objecy-types? And should the object-type 'Outfit' be a C# class OR can I use a generic type like 'object' to hold each 'outfit' in the collection?
//Endpoint setup within the APIcontroller.cs file
[Route("api/getSummerOutfits")]
[HttpGet]
[Authorize]
public string getSummerOutfits()
{
IQueryable<Outfit> outfits = _dbContext.Outfits.Where(outfit => outfit.Type == 'Summer');
return outfits;
}
//Setup for the service within the api.service.ts file
getSummerOutfits(): Observable<Object>
{
return this.httpClient.get('/api/getSummerOutfits').pipe();
}
//A snippet of the response-string when the API is called within Postman
"SELECT \r\n ....... WHERE Outfit.Type = 'Summer'"
I have tried setting the IQueryable<> to contain objects of-type 'outfit' however the response continues to be a string containing the sql-select statement.
The query is declared but never executed.
IQueryable<T> (Remarks section)
Enumeration causes the expression tree associated with an IQueryable object to be executed.
Queries that do not return enumerable results are executed when the Execute method is called.
You have to materialize the query with .ToList() or .AsEnumerable().
public List<Outfit> getSummerOutfits()
{
List<Outfit> outfits = _dbContext.Outfits
.Where(outfit => outfit.Type == 'Summer')
.ToList();
return outfits;
}
While I suggest removing.pipe() as you didn't perform any operation in the response. And return the value of Observable<any[]> or Observable<Outfit[]> if you have write Outfit class/interface.
getSummerOutfits(): Observable<any[]>
{
return this.httpClient.get<any[]>('/api/getSummerOutfits');
}
I'm surprised that even worked. Essentially it passed back an IQueryable<Outfit>.ToString() result.
To return a collection of Outfits Yong Shun's answer covers that using a ToList() and having the return type being an IEnumerable<Outfit>/ ICollection<Outfit>.
As a general rule though I don't recommend passing entities back to views or API, especially for asynchronous AJAX calls as this will typically send far more information than the consumer needs, and potentially opens you up to serialization "traps" with lazy loading.
Instead, define a view model or a DTO, which is a serializable POCO C# object containing just the fields your consumer needs. Then your method becomes:
public IEnumerable<OutfitDto> getSummerOutfits()
{
var outfits = _dbContext.Outfits
.Where(outfit => outfit.Type == 'Summer')
.Select(outfit => new OutfitDto
{
// copy values across here.
}).ToList();
return outfits;
}
This avoids the possibility that a serializer attempts to lazy load navigation properties in Outfit. It reduces the size of the payload by just including the fields that you need, and removes any need to eager-load entire related entities if there are details you want from those. (just reference the related entity properties, EF will build the suitable query) It also avoids confusion especially if you go to pass an outfit DTO back to the server rather than attempting to send what you think is an Entity which is actually nothing more than a serialized JSON object or set of parameters type-cast into an Entity class.

Ember - different keys for serialization and deserialization

I have an issue where an property needs to be serialized and deserialized using to different keys.
In the serializer, the property addresses the key trade:
'tradeId': { key: 'trade' },
This works when addressing the deserialization endpoint.
However, for serialization, the endpoint property is called trade-identifier, requiring the serializer reference to be changed to the following:
'tradeId': { key: 'tradeIdentifier' },
Is there any way to define seperate keys for serialization and deserialization in an Ember serializer?
Thanks to #handlebears for pointing me in the right direction here.
Simply adding a serialize method to the governing serializer file allowed me to reassign the data to the appropriate JSON property:
serialize(snapshot, options){
let json = this._super(...arguments);
json.tradeIdentifier = json.trade;
delete json.trade;
return json;
}
});

Per query JSON serializer in Spring Data Rest

Is there any way to define a JSON serializer per query? I would like to be able to define different JSON output for some queries, something similar to this:
#RepositoryRestResource(collectionResourceRel = "people", path = "person")
public interface PersonJpaRepository extends JpaRepository<Person, Long> {
#JsonSerialize(using = SimplePersonSerializer.class)
List<Person> findAll();
#JsonSerialize(using = FullPersonSerializer.class)
List<Person> findByNameOrderByCreationDateDesc(String name);
}
In this scenario, SimplePersonSerializer should be used to serialize a huge list of results and FullPersonSerializer only a few results.
Without any further information it looks like you want projections. Projections define a subset of an entity's properties. The feature is not mentioned in the official documentation, but in the release notes for Spring Data REST 2.1.
You just need to define an interface that contains the subset of properties:
#Projection(name = "simple", types = Person.class)
interface SimplePerson {
String getFirstName();
String getLastName();
}
You don't have to change your repository. The only thing that changes is the URL you are calling: http://myapp/people?projection=simple.

Django-rest-framework, nested objects in Serializers

I would like to have a nested object inside a serializer instead of just the foreignkey (or url).
As this documentation says, I just had to specify the serializer class of the nested object in the parent serializer:
# Models
class NestedSample(models.Model):
something = models.CharField(max_length=255)
class Sample(models.Model):
thing = models.BooleanField()
nested = models.ForeignKey(NestedSample)
# Serializers
class NestedSampleSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = api_models.NestedSample
class SampleSerializer(serializers.HyperlinkedModelSerializer):
nested = NestedSampleSerializer() # HERE!
class Meta:
model = api_models.Sample
# Views
class NestedSampleViewSet(viewsets.ModelViewSet):
queryset = api_models.NestedSample.objects.all()
serializer_class = api_serializers.NestedSampleSerializer
class SampleViewSet(viewsets.ModelViewSet):
queryset = api_models.Sample.objects.all()
serializer_class = api_serializers.SampleSerializer
This works very well when I get the objects, but it is not possible to create (=POST) Sample objects anymore, I get the error:
{u'non_field_errors': [u'Invalid data']}
I tried to overwrite the create method in the viewset to get the object using the pk:
class SampleViewSet(viewsets.ModelViewSet):
queryset = api_models.Sample.objects.all()
serializer_class = api_serializers.SampleSerializer
def create(self, request):
request.DATA['nested'] = get_object_or_404(api_models.NestedSample, pk=request.DATA['nested'])
return super(SampleViewSet, self).create(request)
But it doesn't work as well.
Any idea?
I also found this question I can relate with which of course solves the problem but do not let me expose the full nested object, so back to the beginning.
Thanks,
I can think of two solutions to this problem. I prefer the first one.
First solution:
Use a django model form to create objects. Override the create and update methods. A sample create method:
def create(self, request):
form = SampleForm(data=request.POST)
if form.is_valid():
instance = form.save(commit=False)
instance.save()
return Response(dict(id=instance.pk), status=status.HTTP_201_CREATED)
return Response(form.errors, status=status.HTTP_400_BAD_REQUEST)
this way you can create Sample objects with any kind of validation you like.
Second solution:
Override get_serializer_class method and return serializer class based on request method. Define two serializers one for post and put and one for list and retrieve.
Can you confirm that you're sending a JSON encoded request - i.e. the request has the content type set to JSON ?
If not, the post is most probably send using form format which doesn't support nested.