Trying to understand why simple jsonix unmarshalling is failing - jsonix

I am new to jsonix and interested mostly in using it to unmarshall xml data. I wrote a very basic test example but have been unsuccessful in getting it to work.
var MyModule = {
name: 'MyModule',
typeInfos: [{
type: 'classInfo',
localName: 'AnyElementType',
propertyInfos: [{
type: 'anyElement',
allowDom: true,
allowTypedObject:true,
name: 'any',
collection: false
}]
}],
elementInfos: [{
elementName: 'sos:Capabilities',
typeInfo: 'MyModule.AnyElementType'
}]
};
var context = new Jsonix.Context([MyModule], {namespacePrefixes: {'http://www.opengis.net/sos/2.0':'sos'}});
var unmarshaller = context.createUnmarshaller();
var data = unmarshaller.unmarshalString('<sos:Capabilities version=\"2.0.0\">hello</sos:Capabilities>');
return data;
I hardcoded a single simple element that has a namespace and contains 'hello' for the test xml. I was interested in the 'any element mapping' for generic unmarshalling. I feel like I have the namespace configured appropriately etc when creating the context yet I keep getting the following error:
Element [sos:Capabilities] could not be unmarshalled as is not known in this context and the property does not allow DOM content. Thoughts? and thanks in advance.

Disclaimer: I am the author of Jsonix.
There are two issues here.
First, you're missing xmlns:sos="http://www.opengis.net/sos/2.0" in your XML.
Second, currently you'll need to define the element name as an object with namespaceURI and localPart. If you just use string, Jsonix will use defaultElementNamespaceURI (which is not defined here). The namespacePrefixes option is currently not applied in elementInfos. This would be a fine feature, please file an issue if you want this.
Here's a working JSFiddle with you module.
var MyModule = {
name: 'MyModule',
typeInfos: [{
type: 'classInfo',
localName: 'AnyElementType',
propertyInfos: [{
type: 'anyElement',
allowDom: true,
allowTypedObject: true,
name: 'any',
collection: false
}]
}],
elementInfos: [{
elementName: {
namespaceURI: 'http://www.opengis.net/sos/2.0',
localPart: 'Capabilities'
},
// 'sos:Capabilities',
typeInfo: 'MyModule.AnyElementType'
}]
};
var context = new Jsonix.Context([MyModule], {
namespacePrefixes: {
'http://www.opengis.net/sos/2.0': 'sos'
}
});
var unmarshaller = context.createUnmarshaller();
var data = unmarshaller.unmarshalString('<sos:Capabilities version=\"2.0.0\" xmlns:sos=\"http://www.opengis.net/sos/2.0\">hello</sos:Capabilities>');
console.log(data);

Related

SNS SDK for NodeJS won't create FIFO topic

When I create a topic using the sns.createTopic (like the code below) it won't accept the booleans and say 'InvalidParameterType: Expected params.Attributes['FifoTopic'] to be a string', even though the docs say to provide boolean value, and when I provide it with a string of 'true' it still doesn't set the topic type to be FIFO, anyone knows why?
Here's the code:
const TOPIC = {
Name: 'test.fifo',
Attributes: {
FifoTopic: true,
ContentBasedDeduplication: true
},
Tags: [{
Key: 'test-key',
Value: 'test-value'
}]
};
sns.createTopic(TOPIC).promise().then(console.log);
Used aws-sdk V2
I sent FifoTopic and ContentBasedDeduplication as strings.
The below code works fine for me
const TOPIC = {
Name: 'test.fifo',
Attributes: {
FifoTopic: "true",
ContentBasedDeduplication: "true"
},
Tags: [{
Key: 'test-key',
Value: 'test-value'
}]
};
let sns = new AWS.SNS();
let response3 =await sns.createTopic(TOPIC).promise();
console.log(response3);
Note: Make sure your lambda has correct permissions.
You will be getting attributes like FifoTopic and ContentBasedDeduplication when performing the getTopicAttributes.
let respo = await sns.getTopicAttributes({
TopicArn:"arn:aws:sns:us-east-1:XXXXXXX:test.fifo"}
).promise();
please find the screenshot

Google Cloud Vision annotateImage feature types don't exist

I'm trying to get more than 10 results in GC Vision with Node.js.
Since I cannot pass the custom request directly to webDetection() I've tried to use annotateImage() instead:
const vision = require('#google-cloud/vision');
const client = new vision.ImageAnnotatorClient();
const webSearchRequest = {
image: {
source: {
imageUri: `gs://${bucket.name}/${filePath}`
}
},
features: [{
maxResults: 50,
type: vision.types.Feature.Type.WEB_DETECTION
}]
};
return client.annotateImage(webSearchRequest).then(webResults => {
console.log(webResults);
}
The output is Cannot read property 'Feature' of undefined
For visibility purpose I am posting my solution from the comments as an answer.
After doing some research and testing with this tool I've seen that the attribute type should be as follow: type: WEB_DETECTION instead of type: vision.types.Feature.Type.WEB_DETECTION.

GraphQL mutation that accepts an array of dynamic size in one request as input with NodeJs

I want to pass an object array of [{questionId1,value1},{questionId2,value2},{questionId3,value3}] of dynamic size in GraphQL Mutation with NodeJS
.........
args: {
input: {
type: new GraphQLNonNull(new GraphQLInputObjectType({
name: 'AssessmentStep3Input',
fields: {
questionId:{
name:'Question ID',
type: new GraphQLNonNull(GraphQLID)
},
value:{
name:'Question Value',
type: new GraphQLNonNull(GraphQLBoolean)
}
}
}))
}
},
.........
How can I do that with the given sample of code?
Thanks
If you want to pass an object array with GraphQL Mutation you need to use "GraphQLList" which allows you to pass an array with dynamic size of given input.
Here is the example
........
........
args: {
input: {
type: new GraphQLNonNull(GraphQLList(new GraphQLInputObjectType({
name: 'AssessmentStep3Input',
fields: {
questionId:{
name:'Question ID',
type: new GraphQLNonNull(GraphQLID)
},
value:{
name:'Question Value',
type: new GraphQLNonNull(GraphQLBoolean)
}
}
}))
)
}
},
........
........
Hope it helps.
Thanks
i just published the article on that, so that you can take a look if you would like to know more detail. This is the repository with the examples, where the createUsers mutation is implemented https://github.com/atherosai/express-graphql-demo/blob/feature/5-modifiers/server/graphql/users/userMutations.js. You can take a look how it is implemented, but in general the above answer is correct. You can input as many objects as you would like to in the array (if you have not implemented some number of items limiting, but it is not there by default).

Data validation in AVRO

I am new to AVRO and please excuse me if it is a simple question.
I have a use case where I am using AVRO schema for record calls.
Let's say I have avro schema
{
"name": "abc",
"namepsace": "xyz",
"type": "record",
"fields": [
{"name": "CustId", "type":"string"},
{"name": "SessionId", "type":"string"},
]
}
Now if the input is like
{
"CustId" : "abc1234"
"sessionID" : "000-0000-00000"
}
I want to use some regex validations for these fields and I want take this input only if it comes in particular format shown as above. Is there any way to specify in avro schema to include regex expression?
Any other data serialization formats which supports something like this?
You should be able to use a custom logical type for this. You would then include the regular expressions directly in the schema.
For example, here's how you would implement one in JavaScript:
var avro = require('avsc'),
util = require('util');
/**
* Sample logical type that validates strings using a regular expression.
*
*/
function ValidatedString(attrs, opts) {
avro.types.LogicalType.call(this, attrs, opts);
this._pattern = new RegExp(attrs.pattern);
}
util.inherits(ValidatedString, avro.types.LogicalType);
ValidatedString.prototype._fromValue = function (val) {
if (!this._pattern.test(val)) {
throw new Error('invalid string: ' + val);
}
return val;
};
ValidatedString.prototype._toValue = ValidatedString.prototype._fromValue;
And how you would use it:
var type = avro.parse({
name: 'Example',
type: 'record',
fields: [
{
name: 'custId',
type: 'string' // Normal (free-form) string.
},
{
name: 'sessionId',
type: {
type: 'string',
logicalType: 'validated-string',
pattern: '^\\d{3}-\\d{4}-\\d{5}$' // Validation pattern.
}
},
]
}, {logicalTypes: {'validated-string': ValidatedString}});
type.isValid({custId: 'abc', sessionId: '123-1234-12345'}); // true
type.isValid({custId: 'abc', sessionId: 'foobar'}); // false
You can read more about implementing and using logical types here.
Edit: For the Java implementation, I believe you will want to look at the following classes:
LogicalType, the base you'll need to extend.
Conversion, to perform the conversion (or validation in your case) of the data.
LogicalTypes and Conversions, a few examples of existing implementations.
TestGenericLogicalTypes, relevant tests which could provide a helpful starting point.

What is the difference between "describe" and "schema.define"?

As I've progressed thru the world of CompoundJS I've came across two ways of defining a schema:
First:
var Product = describe('Product', function () {
property('upc', String);
property('name', String);
set('restPath', pathTo.products);
});
Second:
var Schema = require('jugglingdb').Schema;
var schema = new Schema('memory');
var Product = schema.define('Product', {
upc: { type: Number, index: true },
name: { type: String, limit: 150, index: true },
createdAt: { type: Date, default: Date.now },
modifiedAt: { type: Date, default: Date.now }
}, {
restPath: pathTo.products
});
The first, works, but looks like an old design. The second, does not work, but this is the way to do it according to JugglingDB docs.
Which one should I use? Why wouldn't the second one work for me?
UPDATE:
This is the error I get when I use the second one:
Express
500 TypeError: Cannot call method 'all' of undefined in products controller during "index" action
at Object.index (C:\Users\Eran\Documents\Relay Foods\nutrition-facts-editor\app\controllers\products.js:47:13)
at Array.2 (C:\Users\Eran\Documents\Relay Foods\nutrition-facts-editor\node_modules\compound\node_modules\kontroller\lib\flow-control.js:150:28)
at ActionContext.run [as innerNext] (C:\Users\Eran\Documents\Relay Foods\nutrition-facts-editor\node_modules\compound\node_modules\kontroller\lib\flow-control.js:103:31)
at Controller.BaseController.next (C:\Users\Eran\Documents\Relay Foods\nutrition-facts-editor\node_modules\compound\node_modules\kontroller\lib\base.js:107:22)
at Controller.protectFromForgery (C:\Users\Eran\Documents\Relay Foods\nutrition-facts-editor\node_modules\compound\node_modules\kontroller\lib\helpers.js:76:21)
at Object.protectFromForgeryHook (C:\Users\Eran\Documents\Relay Foods\nutrition-facts-editor\app\controllers\application.js:3:13)
at Array.1 (C:\Users\Eran\Documents\Relay Foods\nutrition-facts-editor\node_modules\compound\node_modules\kontroller\lib\flow-control.js:150:28)
at run (C:\Users\Eran\Documents\Relay Foods\nutrition-facts-editor\node_modules\compound\node_modules\kontroller\lib\flow-control.js:103:31)
... snip ...
I think that describe and define are the same. The issue here is the usage scope which is global in my first implementation and local in the second one. So I'll need it to be global in order to work with the rest of the application.

Resources