Why is GeoDjango not returning my GeoJSON in SRID 4326? - geojson

I have a model with point data stored in srid 2953.
When I serialize this data, I assumed that GeoDjando would convert this to valid GeoJSON by converting the coordinates to SRID 4326.
Maybe I need to specificly tell it to convert this?
From what I have read I understand that CRS has been depreciated from GeoJSON, and that it is only valid in SRID 4326?
class Hpnrecord(models.Model):
...
geom = models.PointField(srid=2953, null=True)
Later in a serializer I have:
class HpnrecordSerializer(serializers.GeoFeatureModelSerializer):
class Meta:
fields = "__all__"
geo_field = "geom"
model = Hpnrecord
When I view the returned data I am getting this:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
2594598.985,
7425392.375
]
},
"properties": {
}
},
as you can see, the coordinates are being displayed as Easting and Northing (the same as what is stored in the model), and not being converted to SRID 4326. My endpoint is expecting to receive this in srid 4326.
How do I specify that I expect the serializaiton to be in SRID 4326?

As you might have noticed, SRID transformations are not done automatically. I have 2 suggestions for you:
Suggestion 1: Store the data in the desired SRID
Before you store the data, you convert it first to your desired srid of 4326. Your model would change:
class Hpnrecord(models.Model):
...
geom = models.PointField(srid=4326, null=True)
Storing the data would look like this:
from django.contrib.gis.geos import Point
...
point = Point(x, y, srid=2953)
point.transform(4326)
model_instance.geom = point
model_instance.save()
Suggestion 2: Use the serializer's to_representation()
You keep your models as they are and you convert the SRID on the fly using the serializer's to_representation() method, see the docs. Note that converting it on the fly will result in a speed penalty, but you can leave the models as they are.
class HpnrecordSerializer(serializers.GeoFeatureModelSerializer):
class Meta:
fields = "__all__"
geo_field = "geom"
model = Hpnrecord
def to_representation(self, instance):
"""Convert `geom` to srid 4326."""
ret = super().to_representation(instance)
ret['geom'].transform(4326)
return ret

Related

How store data to array from json

I have a json file in the format as follows:
{
"recipe_type": [
"vegetarian",
"non-vegetarian"
],
"recipe_times": [
"<30min",
"30-60min",
"60-90min"
],
"recipe_cuisines": [
"arabian",
"european",
"Indian",
"chinese"
]
}
I need to store each list to separate array:
#recipe = new JS.M.Recipe()
#recipe.fetch(#recipe.getRecipeType())
#recipeTypes = #recipe.getRecipeType()//Here data is getting as objetcs..if i use alert to print this. It showing output like "[object Object]"..
I want to store data as follows:
#recipe_type = #recipeTypes.get("recipe_type")
#recipe_times = #recipeTypes.get("recipe_times")//This is wrong
How can I achieve what I want?
If you are using backbone then you must be having underscorejs loaded on the page. If yes, this should work for you
lists = _.values(data)
where data is the JSON object mentioned above.

Swift Filter same location coordinates contained inside an array of objects

I am receiving from Server, a list of Stores information in an array of objects. Below is a sample -
"stores": [
{
"name": “Store 1”,
"number": "5381",
"country": "BELGIE",
"latLng": [
50.730614,
4.231847
]
},
{
"name": "Store 2”,
"number": "5220",
"country": "BELGIE",
"latLng": [
50.730614,
4.231847
]
},
{
"name": "Store 3”,
"number": "3982”,
"country": "BELGIE",
"latLng": [
50.7315706,
4.2303477
]
},
{
"name": "Store 4”,
"number": "4179",
"country": "BELGIE",
"latLng": [
50.7262577,
4.245589
]
}]
What am I trying?:
I need to filter out the stores in the array that has same latLng values.
Why?
I need to identify these 'same latLng' values and add an offset of some value like 0.001 to the latitude value so that when I show these stores on a map, the stores on same location appear side by side.
I found this (answer by Rob B) as reference for this approach.
What I need?
1. How can I filter with values inside of an object in the array?
I tried something like this inside a for loop -
print("\(allStoresInfo.filter({ $0.latLng![0] == $0.latLng![0] }).count)")
This value always returns 4. I know I am missing some basic sense here but need know what it is :-(
After I filter and add the offset for same values, how do I update my array with these updated values?
The following method modifies in place the latitude of each store that matches the latitude of another store:
allStoresInfo.map{ currentStore in allStoresInfo.filter{$0.latLng![0] == currentStore.latLng![0]}.enumerated().forEach{ index, matchingStore in
matchingStore.latLng![0] += Double(index)*0.001
}
}
Just a small piece of advice: don't store lat-long values in an array. Either create a struct/class for them or use a tuple to store them.

dymamic Schemas and nested Maps in Avro

I'm new to Avro, and am trying to write some code to serialize some nested objects.
The structure of the objects looks like this:
class Parcel {
String recipe;
Map<Integer, PluginDump> dumps;
}
class PluginDump {
byte[] state;
Map<String, Param> params;
}
class Param {
Type type; //can be e.g. StringType, BooleanType, etc
Object value;
}
So I can't use a static avro schema - each PluginDump will have a different schema depending on the types within it.
I have written some code which can generate a Schema based on an individual PluginDump.
So when serializing a Parcel, how do I 'put' each PluginDump entry?
Here is my code:
Schema parcelSchema = AvroHelper.getSchema(p);
GenericRecord parcelRecord = new GenericData.Record(parcelSchema);
parcelRecord.put("recipe", p.getRecipe().toJson());
for (Map.Entry<Integer, PluginDump> entry : p.getDumps().entrySet()) {
PluginDump dump = entry.getValue();
Integer uid = entry.getKey();
Schema dumpSchema = AvroHelper.getSchema(dump);//will be different for each PluginDump
parcelRecord.put(????
Any ideas?
I have a feeling my approach is wrong, but I can't find any examples in the documentation of dynamic schema generation or nested maps.
1 When you get GenericRecord parcelRecord = new GenericData.Record(parcelSchema); you have two fields in your record: recipe and dumps, so you can't iterate through the dumps, you must put prepared map with dumps in the second field of record, just like you did it for recipe: parcelRecord.put("dumps", dumps);. But in this case, you'll get ClassCastException, because PluginDump cannot be cast to org.apache.avro.generic.IndexedRecord, so you need to put in parcelRecord a Map of GenericRecords. Also you need this for Map<String, Param> params, cause Param cannot be cast to IndexedRecord too.
2 Then, I think that its better to use Lists instead of Maps, cause avro not very good enough to work with Maps with different types of keys and values.
3 About the Param class: if you will use auto-generated schema, Param class will be presented like this.
"type": "record",
"name": "Param",
"fields": [
{
"name": "type",
"type": {
"type": "record",
"name": "Type",
"namespace": "java.lang.reflect",
"fields": []
}
},
{
"name": "value",
"type": {
"type": "record",
"name": "Object",
"namespace": "java.lang",
"fields": []
}
}
]
As far as avro uses java.lang.reflect, you will lose type field after deserialization, avro will not know what type it was.
If you want to generate avro-schema manually for each Param, considering its type, you can do something like this (I used ClassUtils.getClass from apache commons-lang3, cause standart Class.forName method doesn't always work properly):
public Schema getParamSchema() throws ClassNotFoundException {
List<Schema.Field> fields = new ArrayList<>();
fields.add(new Schema.Field("key", Schema.create(Schema.Type.STRING), "Doc: key field", (Object) null));
Schema.Field f = new Schema.Field("type", ReflectData.get().getSchema(ClassUtils.getClass(((Class) this.type).getName())), "Doc: type field", (Object) null);
f.addProp("java-class", ((Class) this.type).getName());
fields.add(f);
fields.add(new Schema.Field("value", ReflectData.get().getSchema(value.getClass()), "Doc: value field", (Object) null));
return Schema.createRecord(((Class) this.type).getName() + "Param", "Doc: param record", this.getClass().getPackage().getName(), false, fields);
}
But in this case, avro will throw ClassCastException, because it can't cast Class to Boolean, Integer etc. I always had a lot of problems working with avro and java Types and Classes.
So the best advice i think will be to change you model (Parcel, PluginDump and Param i mean) to have less problems with avro. For example you can store type name like a string, and get a Type with reflection after deserializing.

Retrieving data using Grails Domain returns with a Class Key by default

I'm working with a Grails query service and I'm using these the code blocks to retrieve database rows via a domain class.
adjustmentCodeList = AdjustmentCode.findAll {
or {
ilike('description', "%$filterText%")
like('id', "%$filterText%")
}
}
adjustmentCodeList = AdjustmentCode.list()
adjustmentCodeList = AdjustmentCode.list(max: count, offset: from)
It works fine actually, but there is a little problem though. It returns the following list (some sensitive data are omitted):
[
{
"class": "rvms.maintenance.AdjustmentCode",
"id": ...,
"description": ...,
"lastUpdateBy": ...,
"lastUpdateDate": ...,
"status": ...,
"statusDate": ...,
"type": ...
},
{
"class": "rvms.maintenance.AdjustmentCode",
"id": ...,
"description": ...,
"lastUpdateBy": ...,
"lastUpdateDate": ...,
"status": ...,
"statusDate": ...,
"type": ...
},
...
{
"class": "rvms.maintenance.AdjustmentCode",
"id": ...,
"description": ...,
"lastUpdateBy": ...,
"lastUpdateDate": ...,
"status": ...,
"statusDate": ...,
"type": ...
}
]
It includes the domain class name. How can I remove the class key using some config? My current solution is to manually remove the class key from the list by iterating it inside a loop, removing that key one at a time. But maybe... there is another Grails-ly way.
If you want to see the domain, it looks like this:
package rvms.maintenance
import grails.util.Holders
import groovy.sql.Sql
import oracle.jdbc.OracleTypes
import java.sql.Connection
class AdjustmentCode implements Serializable {
String id
String description
String type
String status
Date statusDate
String lastUpdateBy
Date lastUpdateDate
static mapping = {
table '...'
version false
id column : '...'
description column : '...'
type column : '...'
status column : '...'
statusDate column : '...'
lastUpdateBy column : '...'
lastUpdateDate column : '...'
}
Map getAdjustmentCodeValues() {
Map values = [];
values << [id: this.getId()]
values << [description: this.getDescription()]
values << [type: this.getType()]
values << [status: this.getStatus()]
values << [statusDate: this.getStatusDate()]
values << [lastUpdateBy: this.getLastUpdateBy()]
values << [lastUpdateDate: this.getLastUpdateDate()]
return values
}
}
The Grails way to accomplish this is to customize the marshaller. I've explained how to do this with named marshallers in this answer and the same concept applies to your case as well (minus the named portion).

JSON-LD normalization - ignore JSON nesting

I'm working on JSON-LD serialization, and ideally I would like to have a #context which I can add to the existing GeoJSON output (together with some #ids and #types), so that both the Turtle output and the JSON-LD output will normalize to the same triples.
Data is organized as follows: each object/feature has an ID and a name, and data on one or more layers. Per layer, there is a data field, which contains a JSON object.
Example GeoJSON output:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"id": "admr.nl.appingedam",
"name": "Appingedam",
"layers": {
"cbs": {
"data": {
"name": "Appingedam",
"population": 1092
}
},
"admr": {
"data": {
"name": "Appingedam",
"gme_code": 4654,
"admn_level": 3
}
}
}
},
"geometry": {…}
}
]
}
Example Turtle output:
<admr.nl.appingedam>
a :Node ;
dc:title "Appingedam" ;
:createdOnLayer <layer/admr> ;
:layerData <admr.nl.appingedam/admr> ;
:layerData <admr.nl.appingedam/cbs> .
<admr.nl.appingedam/admr>
a :LayerData ;
:definedOnLayer <layer/admr> ;
<layer/admr/name> "Appingedam" ;
<layer/admr/gme_code> "4654" .
<layer/admr/admn_level> "3" .
<admr.nl.appingedam/cbs>
a :LayerData ;
:definedOnLayer <layer/cbs> ;
<layer/cbs/name> "Appingedam" ;
<layer/cbs/population> "1092" ;
The properties object does not have its own URI. Is there a way to create a JSON-LD context which takes the contents of the properties into account, but further 'ignores' its precence?
Answered by Gregg Kellogg on JSON-LD mailing list:
This is something that keeps coming up: having a transparent layer,
that basically folds properties up a level. This was discussed during
the development of JSON-LD, but ultimately it was rejected.
I don't see any prospects for doing something in the short-term, but
it could be revisited in a possible future WG chartered with revising
the spec. Feedback like this is quite useful.
In the mean time, you can play with different JSON-LD encodings that
match your RDF though tools like http://json-ld.org/playground and my
own http://rdf.greggkellogg.net/distiller.
Gregg

Resources