Приложение sql -server-samples 'Todo', которое я пытаюсь получить, находится здесь . Он должен превратить серверную базу данных SQL в API REST с очень небольшим количеством строк кода.
Я не могу выполнить POST или PUT. Выдает ошибку
message: "JSON text is not properly formatted. Unexpected character 'o' is found at position 1.",
code: 'EREQUEST',
number: 13609,
state: 4,
class: 16,
serverName: 'SERVER',
procName: 'createTodo',
lineNumber: 4
Нет проблем с GET, GET по id или DELETE. GET и DELETE отлично работают с SQL Server 2017 Developer, Express и Azure SQL База данных.
Нет ошибок при запуске самих хранимых процедур из SQL Server или Azure. Только при попытке выполнить POST или PUT из командной строки я получаю сообщение об ошибке:
curl -X "POST" "http://localhost:3000/todo"
-i
-H 'Content-Type: application/json'
-d '{"title": "test_title", "description": "test_description", "completed": false, "dueDate": "2014-12-14T00:00:00.000Z"}'
Не вижу ничего плохого в самом тексте JSON. Не вижу никакого символа 'o' в позиции 1. Я попробовал почти все варианты, которые есть с nvarchar, varchar, используя N 'против' в начале строки JSON, изменил описание, чтобы описать, думая, что это может быть зарезервированное слово в SQL Server 2017, похоже, ничего не работает.
Сообщение об ошибке при использовании Azure SQL База данных немного отличается:
JSON text is not properly formatted. Unexpected character \'o\' is found at position 1.
app. js
var express = require('express');
var config = require('config');
var bodyParser = require('body-parser');
var tediousExpress = require('express4-tedious');
var app = express();
app.use(function (req, res, next) {
req.sql = tediousExpress(config.get('connection'));
next();
});
app.use(bodyParser.text());
app.use('/todo', require('./routes/todo'));
// catch 404 and forward to error handler
app.use(function (req, res, next) {
var err = new Error('Not Found: '+ req.method + ":" + req.originalUrl);
err.status = 404;
next(err);
});
app.set('port', process.env.PORT || 3000);
var server = app.listen(app.get('port'), function() {
console.log('Express server listening on port ' + server.address().port);
});
module.exports = app;
todo. js
var router = require('express').Router();
var TYPES = require('tedious').TYPES;
/* GET task listing. */
router.get('/', function (req, res) {
req.sql("select * from todo for json path")
.into(res, '[]');
});
/* GET single task. */
router.get('/:id', function (req, res) {
req.sql("select * from todo where id = @id for json path, without_array_wrapper")
.param('id', req.params.id, TYPES.Int)
.into(res, '{}');
});
/* POST create task. */
router.post('/', function (req, res) {
req.sql("exec createTodo @todo")
.param('todo', req.body, TYPES.NVarChar)
.exec(res);
});
/* PUT update task. */
router.put('/:id', function (req, res) {
req.sql("exec updateTodo @id, @todo")
.param('id', req.params.id, TYPES.Int)
.param('todo', req.body, TYPES.NVarChar)
.exec(res);
});
/* DELETE single task. */
router.delete('/:id', function (req, res) {
req.sql("delete from todo where id = @id")
.param('id', req.params.id, TYPES.Int)
.exec(res);
});
module.exports = router;
default. json
{
"connection":{
"server" : "<name>.database.windows.net",
"userName": "username",
"password": "password",
"options": { "encrypt": "true", "database": "<azure-database-name>" }
}
}
setup. sql - образец таблицы Todo и хранимые процедуры для POST и PUT
/*
CREATE DATABASE TodoDb;
USE TodoDb;
*/
DROP TABLE IF EXISTS Todo
DROP PROCEDURE IF EXISTS createTodo
DROP PROCEDURE IF EXISTS updateTodo
GO
CREATE TABLE Todo (
id int IDENTITY PRIMARY KEY,
title nvarchar(30) NOT NULL,
description nvarchar(4000),
completed bit,
dueDate datetime2 default (dateadd(day, 3, getdate()))
)
GO
INSERT INTO Todo (title, description, completed, dueDate)
VALUES
('Install SQL Server 2016','Install RTM version of SQL Server 2016', 0, '2017-03-08'),
('Get new samples','Go to github and download new samples', 0, '2016-03-09'),
('Try new samples','Install new Management Studio to try samples', 0, '2016-03-12')
GO
create procedure dbo.createTodo(@todo nvarchar(max))
as begin
insert into Todo
select *
from OPENJSON(@todo)
WITH ( title nvarchar(30), description nvarchar(4000),
completed bit, dueDate datetime2)
end
GO
create procedure updateTodo(@id int, @todo nvarchar(max))
as begin
update Todo
set title = json.title, description = json.description,
completed = json.completed, dueDate = json.dueDate
from OPENJSON( @todo )
WITH( title nvarchar(30), description nvarchar(4000),
completed bit, dueDate datetime2) AS json
where id = @id
end
go
select * from todo for json path