Marshalling JSON to XML with jsonix gives invalide XML - node.js

I need to send a xml request to an api for my project. But for security reasons, I cannon't code direct xml in my program. So I decided to use jsonix to marshal JSON to xml, and unmarshal the respond of the request. But I have some problemes.
Here is my xml:
<?xml version = '1.0' encoding='UTF-8'?>
<api>
<authentication>
<login>MyLogin</login>
<password>MyPassword</password>
</authentication>
<command>
<myfunction>
<name>test</name>
</myfunction>
</command>
</api>
With this, I have generated the Mappings with the jsonix-schema-compiler module:
var Search_Module_Factory = function () {
var Search = {
name: "Search",
typeInfos: [{
localName: "Api.Command",
typeName: null,
propertyInfos: [{
name: "myFunction",
required: true,
elementName: {
localPart: "myfunction"
},
typeInfo: ".Api.Command.MyFunction"
}]
}, {
localName: "Api.Authentication",
typeName: null,
propertyInfos: [{
name: "login",
required: true,
elementName: {
localPart: "login"
}
}, {
name: "password",
required: true,
elementName: {
localPart: "password"
}
}]
}, {
localName: "Api.Command.MyFunction",
typeName: null,
propertyInfos: [{
name: "name",
required: true,
elementName: {
localPart: "name"
}
}]
}, {
localName: "Api",
typeName: null,
propertyInfos: [{
name: "authentication",
required: true,
elementName: {
localPart: "authentication"
},
typeInfo: ".Api.Authentication"
}, {
name: "command",
required: true,
elementName: {
localPart: "command"
},
typeInfo: ".Api.Command"
}]
}],
elementInfos: [{
typeInfo: ".Api",
elementName: {
localPart: "api"
}
}]
};
return {
Search: Search
};
};
if (typeof define === "function" && define.amd) {
define([], Search_Module_Factory);
}
else {
var Search_Module = Search_Module_Factory();
if (typeof module !== "undefined" && module.exports) {
module.exports.Search = Search_Module.Search;
}
else {
var Search = Search_Module.Search;
}
}
In my main code, I am marshalling the xml request like this:
var Search = require("./mappings/Search").Search;
var context = new Jsonix.Context([ Search]);
var marshaller = context.createMarshaller();
var originalJS = {
"api": {
"authentication": {
"login" :"mylogin",
"password": "mypassword",
},
"command":{
"myfunction":{
"name": "test"
}
},
}
};
var marshalledXML = marshaller.marshalString(originalJS);
console.log(marshalledXML);
And in the console.log(), instead of showing me something like this, which is the result I want:
<api><authentication><login>mylogin</login><password>mypassword</password></authentication><command><myfunction><name>test</name></myfunction></command></api>
It's returning something like this:
<api><authentication><login>mylogin</login><password>mypassword</password></authentication><command/></api>
The tag command is always empty, and I don't understand what I'm doing wrong.
Thank for your help

Related

ts mongoose query specific string attribute as string array (not object array)

I have this mongoose schema, and I want to query all IP attributes as a string array.
like [IP,IP,IP,IP] this, not [ { ip : ip} ]
const proxyIpSchema = new Schema<IProxyIp>({
ip: {
type: String,
required: true,
//ignore duplicate ip
unique: true,
},
port: {
type: Number,
required: false,
default: null
},
reason: {
type: String,
required: true,
default: 'Unknown Detection.'
}
},
{
timestamps: true,
}
);
I cant use a map function because it will eat the backend processing power. like this
I want all ips as a string array
//get all ips from mongo db and push to redis
await ProxyIp.find({}, { ip: 1 }).then(async (docs) => {
docs.map(async (doc) => {
await this.RedisClient?.sAdd(redisTable, doc.ip);
});
}).catch((err) => {
});
Here's one way you can put all the "ip"s into a single array (within an object).
db.ProxyIp.aggregate([
{
"$group": {
"_id": null,
"ips": {
"$push": "$ip"
}
}
},
{
"$unset": "_id"
}
])
Example output:
[
{
"ips": [
"102.118.108.76",
"34.234.240.83",
"123.76.73.33",
"134.81.197.85",
"193.122.45.195",
"54.25.18.14",
"185.68.124.193",
"3.105.130.68",
"52.72.204.78",
"117.212.118.167",
"199.155.140.226",
"64.194.68.59",
"57.4.147.57",
"190.116.4.243",
"179.111.74.98",
...
]
}
[
Try it on mongoplayground.net.

How to set "seen:true" in array of messages in mongoose

I am newbie in mongodb world, i was stuck in on Mongoose query.
basically I was developing a chat application for my website. the chat schema of my website shown below
const LiveChat = mongoose.Schema({
members: [String],
messages: [{
sender: String,
reciever: String,
text: String,
seen: {
type: Boolean,
default: false
},
date: {
type: Date,
default: Date.now
}
}],
}, { timestamps: true });
for exapmle collection will looks like this
[
{
"_id":"627749f8dc5927d660f76172",
"members":[
"626a250d11ed1b096883aed1",
"626a234611ed1b096883ae13"
],
"messages":[
{
"sender":"626a250d11ed1b096883aed1",
"reciever":"626a234611ed1b096883ae13",
"text":"hello there!.",
"seen":false,
"_id":"6278b0c38031894a9ceefeae",
"date":"2022-05-09T06:12:19.857Z"
},
{
"sender":"626a250d11ed1b096883aed1",
"reciever":"626a234611ed1b096883ae13",
"text":"how are you?.",
"seen":false,
"_id":"6278b0e18031894a9ceefede",
"date":"2022-05-09T06:12:49.680Z"
},
{
"sender":"626a234611ed1b096883ae13",
"reciever":"626a250d11ed1b096883aed1",
"text":"hello Rupesh",
"seen":false,
"_id":"6278b1438031894a9ceeff98",
"date":"2022-05-09T06:14:27.388Z"
},
{
"sender":"626a234611ed1b096883ae13",
"reciever":"626a250d11ed1b096883aed1",
"text":"we are doing well",
"seen":false,
"_id":"6278b1588031894a9ceeffe0",
"date":"2022-05-09T06:14:48.203Z"
},
{
"sender":"626a250d11ed1b096883aed1",
"reciever":"626a234611ed1b096883ae13",
"text":"okay",
"seen":false,
"_id":"6278b1ed8031894a9cef0099",
"date":"2022-05-09T06:17:17.421Z"
}
],
"createdAt":"2022-05-08T04:41:28.416Z",
"updatedAt":"2022-05-09T06:17:17.420Z",
"__v":0
},
{
"_id":"62762021be68a5e2de8dc2d2",
members: ["626a250d11ed1b096883aed1", "6273bc879ff276ac89f9c4f8"]
"messages":[
{
"sender":"626a250d11ed1b096883aed1",
"reciever":"6273bc879ff276ac89f9c4f8",
"text":"hello there!",
"seen":false,
"_id":"6277ac0ba5fe501f98e1421e",
"date":"2022-05-08T11:39:55.263Z"
},
{
"sender":"626a250d11ed1b096883aed1",
"reciever":"6273bc879ff276ac89f9c4f8",
"text":"can you please tell me what is the date of start a project task",
"seen":false,
"_id":"6277ac30a5fe501f98e1424c",
"date":"2022-05-08T11:40:32.472Z"
},
],
"createdAt":"2022-05-07T07:30:41.447Z",
"updatedAt":"2022-05-08T12:24:31.400Z",
"__v":0
}
]
now i want to set seen:true for all messages into messages array whose sender == "626a250d11ed1b096883aed1" ( sender_id and conversation_id are given from req.body into a API).
for all messages in messages array:
seen:false means message is not seen by reciever
seen:true means message is seen by reciever
i was trying following way into my express API but its not wokring...
cosnt {conversation_id, sender_id} = req.body;
LiveChat.findByIdAndUpdate({ _id: conversation_id },
[{
$set: {
'messages.seen': { $cond: [{ $eq: ['messages.sender', sender_id] }, true, false] }
}
}]
,
{
new: true,
useFindAndModify: true,
}
please help me to write this query...
Here's one way you could do the update using "arrayFilters".
db.collection.update({
"_id": "627749f8dc5927d660f76172" // given _id
},
{
"$set": {
"messages.$[x].seen": true
}
},
{
"arrayFilters": [
{
"x.sender": "626a250d11ed1b096883aed1" // given sender
}
]
})
Try it on mongoplayground.net.

Get all data from subdocument via graphql

Model
const mongoose=require('mongoose');
const CustomerGeneralInformation = require('./CustomerGeneralInformation').schema;
const CustomerContact = require('./CustomerContact').schema;
const CustomerFinance=require('./CustomerFinancial').schema;
const CustomerPersonalData=require('./CustomerPersonalData').schema;
const CustomerIdentification=require('./CustomerIdentification').schema;
const Schema=mongoose.Schema;
const CustomerSchema=new Schema({
generalInformation: [CustomerGeneralInformation],
contactData: [CustomerContact],
financialData:[CustomerFinance],
personalData:[CustomerPersonalData],
identificationData:[CustomerIdentification]
});
module.exports=mongoose.model('Customer',CustomerSchema);
Graphql Schema
const RootQuery=new GraphQLObjectType({
name:'RootQueryType',
fields:{
customers:{
type: new GraphQLList(CustomerType),
resolve(parent,args){
return customer.find({});
}
}
}
});
GraphiQl
{
customers
{
id
generalInformation{
purposeOfBusiness
}
contactData{
phone
email
countryResidence
mailbox
houseNo
zip
city
}
financialData{
taxNo
countryTaxation
refBankIban
StringrefBankBic
refBankIban
}
}
}
Result
{
"data": {
"customers": [
{
"id": "5fa0f8ea4e028a2cf8d24c3f",
"generalInformation": {
"purposeOfBusiness": null
},
"contactData": {
"phone": null,
"email": null,
"countryResidence": null,
"mailbox": null,
"houseNo": null,
"zip": null,
"city": null
},
"financialData": {
"taxNo": null,
"countryTaxation": null,
"refBankIban": null,
"StringrefBankBic": null
}
}
]
}
}
SO I have created a customer model which have an id(autogenerated by mongodb) and 5 other fields of schema type.
I have used graphql for creating apis.
Everything is working fine, I have created mutations to add data, its all tested in mongo that data is being saved.
But if you check my graphql output I am unable to query subdocuments, it shows null. I want list of all subdocuments with data.
PlEASE HELP
I had tried this way and its working perfectly,
Firstly as you are passing the whole model in your new Customer model so instead of that I just have stored the ID as a reference.
const CustomerSchema = new mongoose.Schema(
{
generalInformation: {
type: mongoose.Schema.Types.ObjectId,
ref: "GeneralInfo"
},
contactData: { type: mongoose.Schema.Types.ObjectId, ref: "ContactData" },
financialData: {
type: mongoose.Schema.Types.ObjectId,
ref: "FinacialData"
},
personalData: { type: mongoose.Schema.Types.ObjectId, ref: "PersonalData" }
},
{
timestamps: true
}
);
After that, for CustomerType, I had done this
const CustomerType = new GraphQLObjectType({
name: "Customer",
fields: () => ({
id: { type: GraphQLID },
customerContact: {
type: CustomerContactType,
resolve(parent, args) {
return CustomerContact.findById(parent.contactData);
}
},
generalInformation: {
type: CustomerGeneralType,
resolve(parent, args) {
return CustomerGeneral.findById(parent.generalInformation);
}
},
financialData: {
type: CustomerFinanceType,
resolve(parent, args) {
return CustomerFinance.findById(parent.financialData);
}
},
personalData: {
type: CustomerPersonalType,
resolve(parent, args) {
return CustomerPersonal.findById(parent.personalData);
}
}
})
});
And them for RootQuery
customers: {
type: new GraphQLList(CustomerType),
resolve(parent, args) {
return Customar.find({});
}
}
and here is my Query:
{
customers{
id
generalInformation{
purposeOfBusiness
}
customerContact{
phone
email
countryResidence
}
financialData{
taxNo
}
}
}
And Output
{
"data": {
"customers": [
{
"id": "5fa3fe066f0fda0568e56456",
"generalInformation": {
"purposeOfBusiness": "Test Purpose"
},
"customerContact": {
"phone": "123456798",
"email": "test#demo.com",
"countryResidence": "Pak"
},
"financialData": {
"taxNo": "120033244"
}
}
]
}
}

Fastify schema validation multipart/form-data (body should be object)

Multipart form data file uplaod time comming error body should be object, and i am using ajv plugin also, still i am using same issue. below is my reference code.
app.js
const fastify = require('fastify')({
logger: true
});
const Ajv = require('ajv');
const ajv = new Ajv({
useDefaults: true,
coerceTypes: true,
$data: true,
extendRefs: true
});
ajv.addKeyword("isFileType", {
compile: (schema, parent, it) => {
parent.type = "file";
delete parent.isFileType;
return () => true;
},
});
fastify.setSchemaCompiler((schema) => ajv.compile(schema));
routes.js
schema: {
tags: [{
name: 'Category'
}],
description: 'Post category data',
consumes: ['multipart/form-data'],
body: {
type: 'object',
isFileType: true,
properties: {
name: {
type: 'string'
},
thumb_url: {
isFileType: true,
type: 'object'
},
img_url: {
isFileType: true,
type: 'object'
},
status: {
type: 'number',
enum: [0, 1],
default: 1
}
},
required: ['name', 'thumb_url', 'img_url']
},
response: {
201: {
type: 'object',
properties: categoryProperties
}
}
}
response
{
"statusCode": 400,
"error": "Bad Request",
"message": "body should be object"
}
I suspect the error is in the way I send the data, but I am having trouble figuring it out. I have read about this error and it seems to be generated when an object is passed to formData, but I am sending a string so I don't understand why it happens. thanks in advance!
I think your configuration to manage multipart is wrong and the schema should be fixed as this working example:
const fastify = require('fastify')({ logger: true })
fastify.register(require('fastify-multipart'), {
addToBody: true
})
const Ajv = require('ajv')
const ajv = new Ajv({
useDefaults: true,
coerceTypes: true,
$data: true,
extendRefs: true
})
ajv.addKeyword('isFileType', {
compile: (schema, parent, it) => {
parent.type = 'file'
delete parent.isFileType
return () => true
}
})
fastify.setSchemaCompiler((schema) => ajv.compile(schema))
fastify.post('/', {
schema: {
tags: [{
name: 'Category'
}],
description: 'Post category data',
consumes: ['multipart/form-data'],
body: {
type: 'object',
properties: {
name: { type: 'string' },
thumb_url: { isFileType: true },
img_url: { isFileType: true },
status: {
type: 'number',
enum: [0, 1],
default: 1
}
},
required: ['name', 'thumb_url', 'img_url']
}
}
}, async (req, reply) => {
let filepath = path.join(__dirname, `${req.body.thumb_url[0].filename}-${Date.now()}`)
await fs.writeFile(filepath, (req.body.thumb_url[0].data))
filepath = path.join(__dirname, `${req.body.img_url[0].filename}-${Date.now()}`)
await fs.writeFile(filepath, (req.body.img_url[0].data))
return req.body
})
fastify.listen(3000)
Call it with this request:
curl -X POST \
http://127.0.0.1:3000/ \
-H 'content-type: multipart/form-data' \
-F 'thumb_url=#/home/wks/example-file' \
-F 'img_url=#/home/wks/example-file' \
-F 'name=fooo'
You will get:
{
"thumb_url":[
{
"data":{
"type":"Buffer",
"data":[
97,
115,
100,
10
]
},
"filename":"example-file",
"encoding":"7bit",
"mimetype":"application/octet-stream",
"limit":false
}
],
"img_url":[
{
"data":{
"type":"Buffer",
"data":[
97,
115,
100,
10
]
},
"filename":"example-file",
"encoding":"7bit",
"mimetype":"application/octet-stream",
"limit":false
}
],
"name":"foo",
"status":1
}

Can't call a nested key in Mongoose and Express (undefined)

I have a Mongoose Schema that display results. I can display the result array but not what's inside.
{
"_id": {
"$oid": "5cfa15e123d2f414da760635"
},
"objectID": 21078,
"cars_getroute": "volvo-123-gt-coach-1967-1968",
"gm_url": "https://www.url.com",
"results": [
{
"marque": "Volvo",
"model": "Amazon 123 GT",
"model_year": "1967",
"price_str": "£4 982",
"price_int": 4982,
"price_currency": "£",
"sold": true,
"auction_house": "Anglia Car Auctions",
"auction_country": "Grande-Bretagne",
"auction_date": "25 août 2018",
"auction_datetime": "2018-08-25",
"auction_url": null,
"image_urls": null,
"price_int_eu": 5523
},
{
"marque": "Volvo",
"model": "Amazon 123 GT",
"model_year": "1968",
"price_str": "CHF9 000",
"price_int": 9000,
"price_currency": "CHF",
"sold": true,
"auction_house": "Oldtimer Galerie",
"auction_country": "Suisse",
"auction_date": "29 avril 2017",
"auction_datetime": "2017-04-29",
"auction_url": null,
"image_urls": "https://www.url.com/img/auctions/car/thumb/17-4-11-f8a85a227775570cdeb80ba0a437cc40.jpg",
"price_int_eu": 8309
},
{
"marque": "Volvo",
"model": "Amazon 123 GT",
"model_year": "1968",
"price_str": "Estimate £6 000 - £7 000 (unsold)",
"price_int": null,
"price_currency": null,
"sold": false,
"auction_house": "Herefordshire Vintage Auctions",
"auction_country": "Grande-Bretagne",
"auction_date": "20 octobre 2016",
"auction_datetime": "2016-10-20",
"auction_url": "http://www.url.com/Motor_details.php?pid=188&motor=188_01.jpg",
"image_urls": "https://www.url.com/img/auctions/car/2016-10-4a5a09eeb5c685e053e421c45656dcf7.jpg",
"price_int_eu": null
}
]
}
And the model:
const DemocarauctionSchema = new Schema({
objectID: {
type: Number
},
cars_getroute: {
type: String
},
gm_url: {
type: String
},
"results": { type: [{
marque: {
type: String
},
model: {
type: String
},
model_year: {
type: String
},
price_str: {
type: String
},
prince_int: {
type: Number
},
price_currency: {
type: String
},
sold: {
type: Boolean
},
auction_house: {
type: String
},
auction_country: {
type: String
},
auction_date: {
type: String
},
auction_datetime: {
type: String
},
auction_url: {
type: String
},
image_urls: {
type: String
},
price_int_eu: {
type: Number
},
}]}
},
{
collection: 'democarficheauction'
});
And when I call console.log(democarauctions.results.marque), nothing appears.
Is it a problem with my Schema ? Because There are multiple "marque" keys in the "results" array ?
It's working well with gm_url, objectId and cars_getroute.
EDIT: here is my Express route:
router.get('/demo/:cars_getroute', (req, res, next) => {
Promise.all([Democar.findOne({ cars_getroute: req.params.cars_getroute }), Democarauction.findOne({ cars_getroute: req.params.cars_getroute })])
.then(result => {
const [democars, democarauctions] = result;
console.log(democarauctions.results.marque)
res.render('demo/fichecar-demo', {
marque: democars.marque,
modele: democars.modele,
sous_modele: democars.sous_modele,
sous_modele2: democars.sous_modele2,
type: democars.type,
precision: democars.precision,
years_interval: democars.years_interval,
cote_actual: democars.cote_actual.toLocaleString('fr-FR'),
img_url: democars.img_url,
cote_1989_eu_excp: democars.cote.cote_1989.cote_1989_eu.cote_1989_excp,
cote_1989_eu_concours: democars.cote.cote_1989.cote_1989_eu.cote_1989_concours,
cote_1989_eu_base: democars.cote.cote_1989.cote_1989_eu.cote_1989_base,
cote_1989_eu_be: democars.cote.cote_1989.cote_1989_eu.cote_1989_be,
cote_1989_eu_me: democars.cote.cote_1989.cote_1989_eu.cote_1989_me,
cote_1989_eu_ar: democars.cote.cote_1989.cote_1989_eu.cote_1989_ar,
cote_1989_eu_epa: democars.cote.cote_1989.cote_1989_eu.cote_1989_epa,
cote_2004_excp: democars.cote.cote_2004.cote_2004_excp,
cote_2004_concours: democars.cote.cote_2004.cote_2004_concours,
cote_2004_base: democars.cote.cote_2004.cote_2004_base,
cote_2004_be: democars.cote.cote_2004.cote_2004_be,
cote_2004_me: democars.cote.cote_2004.cote_2004_me,
cote_2004_ar: democars.cote.cote_2004.cote_2004_ar,
cote_2004_epa: democars.cote.cote_2004.cote_2004_epa,
cote_2014_excp: democars.cote.cote_2014.cote_2014_excp,
cote_2014_concours: democars.cote.cote_2014.cote_2014_concours,
cote_2014_base: democars.cote.cote_2014.cote_2014_base,
cote_2014_be: democars.cote.cote_2014.cote_2014_be,
cote_2014_me: democars.cote.cote_2014.cote_2014_me,
cote_2014_ar: democars.cote.cote_2014.cote_2014_ar,
cote_2014_epa: democars.cote.cote_2014.cote_2014_epa,
cote_2017_excp: democars.cote.cote_2017.cote_2017_excp,
cote_2017_concours: democars.cote.cote_2017.cote_2017_concours,
cote_2017_base: democars.cote.cote_2017.cote_2017_base,
cote_2017_be: democars.cote.cote_2017.cote_2017_be,
cote_2017_me: democars.cote.cote_2017.cote_2017_me,
cote_2017_ar: democars.cote.cote_2017.cote_2017_ar,
cote_2017_epa: democars.cote.cote_2017.cote_2017_epa,
cote_2019_excp: democars.cote.cote_2019.cote_2019_excp,
cote_2019_concours: democars.cote.cote_2019.cote_2019_concours,
cote_2019_base: democars.cote.cote_2019.cote_2019_base,
cote_2019_be: democars.cote.cote_2019.cote_2019_be,
cote_2019_me: democars.cote.cote_2019.cote_2019_me,
cote_2019_ar: democars.cote.cote_2019.cote_2019_ar,
cote_2019_epa: democars.cote.cote_2019.cote_2019_epa,
cote_actual_chart: democars.cote_actual,
cote_actual_excp: democars.cote.cote_2019.cote_2019_excp.toLocaleString('fr-FR'),
cote_actual_concours: democars.cote.cote_2019.cote_2019_concours.toLocaleString('fr-FR'),
cote_actual_base: democars.cote.cote_2019.cote_2019_base.toLocaleString('fr-FR'),
cote_actual_be: democars.cote.cote_2019.cote_2019_be.toLocaleString('fr-FR'),
cote_actual_me: democars.cote.cote_2019.cote_2019_me.toLocaleString('fr-FR'),
cote_actual_ar: democars.cote.cote_2019.cote_2019_ar.toLocaleString('fr-FR'),
cote_actual_epa: democars.cote.cote_2019.cote_2019_epa.toLocaleString('fr-FR'),
perfo_1989: democars.performance.perfo1989,
perfo_2004: democars.performance.perfo2004,
perfo_2014: democars.performance.perfo2014,
perfo_2017: democars.performance.perfo2017,
results: democarauctions.results,
marqueauction: democarauctions.results.marque
}
});
})
.catch(err => {
// handle error.
console.log(err);
})
});
Here is my HTML template:
<div class="results__container--content">
{{#each results}}
<div class="results__container--box">
<h1>{{marqueauction}}</h1>
</div>
{{else}}
<div class="results__container--box">
<p>Aucun résultat d'enchères n'est disponible pour ce modèle.</p>
</div>
{{/each}}
</div>
results is an array, you should loop over the array to get the value of marque
let marqueauction = [];
for(let i =0; i < democarauctions.results.length; i++) {
marqueauction.push(democarauctions.results[i].marque)
}
res.render('demo/fichecar-demo', {
marqueauction: marqueauction
});
You can now render the marque in your HTML by looping over the marqueauction.

Resources