From 777fac191e87411761be0c21f3a522a399ef06aa Mon Sep 17 00:00:00 2001 From: Mr-Rm Date: Wed, 13 May 2026 12:02:55 +0400 Subject: [PATCH 1/4] =?UTF-8?q?fix=20#1679:=20=D0=B4=D0=BE=D0=B1=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=20=D0=BC=D0=B5=D1=82=D0=BE=D0=B4=20?= =?UTF-8?q?=D0=9E=D1=82=D0=BA=D1=80=D1=8B=D1=82=D1=8C=D0=9F=D0=BE=D1=82?= =?UTF-8?q?=D0=BE=D0=BA()=20=D0=BE=D0=B1=D1=8A=D0=B5=D0=BA=D1=82=D0=B0=20?= =?UTF-8?q?=D0=A7=D1=82=D0=B5=D0=BD=D0=B8=D0=B5JSON?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Json/JSONReader.cs | 37 ++++++++++++++++++- tests/json/test-json_reader.os | 12 ++++++ 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/src/OneScript.StandardLibrary/Json/JSONReader.cs b/src/OneScript.StandardLibrary/Json/JSONReader.cs index 444907ee2..f00b0514c 100644 --- a/src/OneScript.StandardLibrary/Json/JSONReader.cs +++ b/src/OneScript.StandardLibrary/Json/JSONReader.cs @@ -5,15 +5,16 @@ This Source Code Form is subject to the terms of the at http://mozilla.org/MPL/2.0/. ----------------------------------------------------------*/ -using System; -using System.IO; using Newtonsoft.Json; using OneScript.Commons; using OneScript.Contexts; using OneScript.Exceptions; +using OneScript.StandardLibrary.Binary; using OneScript.StandardLibrary.Text; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; +using System; +using System.IO; namespace OneScript.StandardLibrary.Json { @@ -266,6 +267,38 @@ public void OpenFile(string JSONFileName, IValue encoding = null) }; } + /// + /// Устанавливает поток для чтения JSON данным объектом. + /// Если перед вызовом данного метода уже производилось чтение JSON из другого файла, строки или потока, + /// то чтение прекращается и объект инициализируется для чтения из указанного потока. + /// + /// + /// Поток для чтения текста JSON. + /// + /// Позволяет задать кодировку входного потока. + [ContextMethod("ОткрытьПоток", "OpenStream")] + public void OpenStream(IValue streamContext, IValue encoding = null) + { + if (IsOpen()) + Close(); + + var stream = streamContext switch + { + GenericStream s => s.GetUnderlyingStream(), + FileStreamContext s => s.GetUnderlyingStream(), + MemoryStreamContext s => s.GetUnderlyingStream(), + + _ => throw RuntimeException.InvalidNthArgumentType(1) + }; + + var enc = encoding != null ? TextEncodingEnum.GetEncoding(encoding) : System.Text.Encoding.UTF8; + + _reader = new JsonReaderInternal(new StreamReader(stream, enc)) + { + SupportMultipleContent = true + }; + } + /// /// Если текущее значение – начало массива или объекта, то пропускает его содержимое и конец. /// Для остальных типов значений работает аналогично методу Прочитать(). diff --git a/tests/json/test-json_reader.os b/tests/json/test-json_reader.os index a3e98504a..4679e5b35 100644 --- a/tests/json/test-json_reader.os +++ b/tests/json/test-json_reader.os @@ -24,6 +24,8 @@ СписокТестов.Добавить("Тест_Должен_ПроверитьПропускНезавершенногоМассива"); СписокТестов.Добавить("Тест_Должен_ПроверитьПропускМассиваСВложенными"); СписокТестов.Добавить("Тест_Должен_ПроверитьПропускОбъектаСВложениями"); + + СписокТестов.Добавить("Тест_Должен_ПроверитьОткрытиеПотока"); Возврат СписокТестов; КонецФункции @@ -219,3 +221,13 @@ юТест.ПроверитьРавенство(ТипЗначенияJSON.Число, Чтение.ТипТекущегоЗначения); юТест.ПроверитьРавенство(5, Чтение.ТекущееЗначение); КонецПроцедуры + +Процедура Тест_Должен_ПроверитьОткрытиеПотока() Экспорт + БДД = ПолучитьБуферДвоичныхДанныхИзСтроки("{""ответ"":42}"); + Поток = Новый ПотокВПамяти(БДД); + Чтение = Новый ЧтениеJSON; + Чтение.ОткрытьПоток(Поток); + Json = ПрочитатьJSON(Чтение); + + юТест.ПроверитьРавенство(42, Json.Ответ); +КонецПроцедуры From 0297f46ee4cdcd5c09b4f35d5f84adb4641cf3c6 Mon Sep 17 00:00:00 2001 From: Mr-Rm Date: Wed, 13 May 2026 21:42:40 +0400 Subject: [PATCH 2/4] =?UTF-8?q?=D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7?= =?UTF-8?q?=D0=BE=D0=B2=D0=B0=D0=BD=20=D0=BE=D0=B1=D1=89=D0=B8=D0=B9=20?= =?UTF-8?q?=D0=B8=D0=BD=D1=82=D0=B5=D1=80=D1=84=D0=B5=D0=B9=D1=81=20=D0=9F?= =?UTF-8?q?=D0=BE=D1=82=D0=BE=D0=BA=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Binary/FileStreamContext.cs | 2 +- src/OneScript.StandardLibrary/Json/JSONReader.cs | 14 +++----------- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/src/OneScript.StandardLibrary/Binary/FileStreamContext.cs b/src/OneScript.StandardLibrary/Binary/FileStreamContext.cs index 6386898a6..70f517935 100644 --- a/src/OneScript.StandardLibrary/Binary/FileStreamContext.cs +++ b/src/OneScript.StandardLibrary/Binary/FileStreamContext.cs @@ -22,7 +22,7 @@ namespace OneScript.StandardLibrary.Binary /// Следует учитывать, что помимо буферизации существует кэширование чтения и записи файлов в операционной системе, на которое невозможно повлиять программно. /// [ContextClass("ФайловыйПоток", "FileStream")] - public class FileStreamContext : AutoContext, IStreamWrapper, IDisposable + public class FileStreamContext : AutoContext, IDisposable, IStreamWrapper { private readonly FileStream _underlyingStream; diff --git a/src/OneScript.StandardLibrary/Json/JSONReader.cs b/src/OneScript.StandardLibrary/Json/JSONReader.cs index f00b0514c..954f1f53d 100644 --- a/src/OneScript.StandardLibrary/Json/JSONReader.cs +++ b/src/OneScript.StandardLibrary/Json/JSONReader.cs @@ -272,25 +272,17 @@ public void OpenFile(string JSONFileName, IValue encoding = null) /// Если перед вызовом данного метода уже производилось чтение JSON из другого файла, строки или потока, /// то чтение прекращается и объект инициализируется для чтения из указанного потока. /// - /// + /// /// Поток для чтения текста JSON. /// /// Позволяет задать кодировку входного потока. [ContextMethod("ОткрытьПоток", "OpenStream")] - public void OpenStream(IValue streamContext, IValue encoding = null) + public void OpenStream(IStreamWrapper streamContext, IValue encoding = null) { if (IsOpen()) Close(); - - var stream = streamContext switch - { - GenericStream s => s.GetUnderlyingStream(), - FileStreamContext s => s.GetUnderlyingStream(), - MemoryStreamContext s => s.GetUnderlyingStream(), - _ => throw RuntimeException.InvalidNthArgumentType(1) - }; - + var stream = streamContext.GetUnderlyingStream(); var enc = encoding != null ? TextEncodingEnum.GetEncoding(encoding) : System.Text.Encoding.UTF8; _reader = new JsonReaderInternal(new StreamReader(stream, enc)) From 0ca87f7de220c33c7aa5f211ae1b1eebf64f4e18 Mon Sep 17 00:00:00 2001 From: Mr-Rm Date: Thu, 14 May 2026 12:41:20 +0400 Subject: [PATCH 3/4] =?UTF-8?q?=D1=81=D0=BE=D1=85=D1=80=D0=B0=D0=BD=D1=8F?= =?UTF-8?q?=D1=82=D1=8C=20=D0=BF=D0=BE=D1=82=D0=BE=D0=BA=20=D0=BF=D1=80?= =?UTF-8?q?=D0=B8=20=D0=B7=D0=B0=D0=BA=D1=80=D1=8B=D1=82=D0=B8=D0=B8=20?= =?UTF-8?q?=D1=87=D1=82=D0=B5=D0=BD=D0=B8=D1=8F;=20=D1=83=D0=B1=D1=80?= =?UTF-8?q?=D0=B0=D0=BD=D0=B0=20=D0=BD=D0=B5=D0=BD=D1=83=D0=B6=D0=BD=D0=B0?= =?UTF-8?q?=D1=8F=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BA=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Json/JSONReader.cs | 11 ++++----- tests/json/test-json_reader.os | 24 +++++++++++++++++++ 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/OneScript.StandardLibrary/Json/JSONReader.cs b/src/OneScript.StandardLibrary/Json/JSONReader.cs index 954f1f53d..18ae4a365 100644 --- a/src/OneScript.StandardLibrary/Json/JSONReader.cs +++ b/src/OneScript.StandardLibrary/Json/JSONReader.cs @@ -244,8 +244,7 @@ public void Close() [ContextMethod("ОткрытьФайл", "OpenFile")] public void OpenFile(string JSONFileName, IValue encoding = null) { - if (IsOpen()) - Close(); + Close(); StreamReader _fileReader; @@ -279,13 +278,12 @@ public void OpenFile(string JSONFileName, IValue encoding = null) [ContextMethod("ОткрытьПоток", "OpenStream")] public void OpenStream(IStreamWrapper streamContext, IValue encoding = null) { - if (IsOpen()) - Close(); + Close(); var stream = streamContext.GetUnderlyingStream(); var enc = encoding != null ? TextEncodingEnum.GetEncoding(encoding) : System.Text.Encoding.UTF8; - _reader = new JsonReaderInternal(new StreamReader(stream, enc)) + _reader = new JsonReaderInternal(new StreamReader(stream, enc, leaveOpen:true)) { SupportMultipleContent = true }; @@ -333,8 +331,7 @@ public bool Read() [ContextMethod("УстановитьСтроку", "SetString")] public void SetString(string JSONString) { - if (IsOpen()) - Close(); + Close(); _reader = new JsonReaderInternal(new StringReader(JSONString)) { diff --git a/tests/json/test-json_reader.os b/tests/json/test-json_reader.os index 4679e5b35..4a7cdf8b3 100644 --- a/tests/json/test-json_reader.os +++ b/tests/json/test-json_reader.os @@ -26,6 +26,8 @@ СписокТестов.Добавить("Тест_Должен_ПроверитьПропускОбъектаСВложениями"); СписокТестов.Добавить("Тест_Должен_ПроверитьОткрытиеПотока"); + СписокТестов.Добавить("Тест_Должен_ПроверитьПовторноеОткрытиеПотока"); + СписокТестов.Добавить("Тест_Должен_ПроверитьСохранениеПотокаПослеЗакрытияЧтения"); Возврат СписокТестов; КонецФункции @@ -231,3 +233,25 @@ юТест.ПроверитьРавенство(42, Json.Ответ); КонецПроцедуры + +Процедура Тест_Должен_ПроверитьПовторноеОткрытиеПотока() Экспорт + БДД = ПолучитьБуферДвоичныхДанныхИзСтроки("{""ответ"":42}"); + Поток = Новый ПотокВПамяти(БДД); + Чтение = Новый ЧтениеJSON; + Чтение.ОткрытьПоток(Поток); + Чтение.ОткрытьПоток(Поток); // повторно + Json = ПрочитатьJSON(Чтение); + + юТест.ПроверитьРавенство(42, Json.Ответ); +КонецПроцедуры + +Процедура Тест_Должен_ПроверитьСохранениеПотокаПослеЗакрытияЧтения() Экспорт + БДД = ПолучитьБуферДвоичныхДанныхИзСтроки("{""ответ"":42}"); + Поток = Новый ПотокВПамяти(БДД); + Чтение = Новый ЧтениеJSON; + Чтение.Закрыть(); + Чтение.ОткрытьПоток(Поток); // Поток должен остаться открытым + Json = ПрочитатьJSON(Чтение); + + юТест.ПроверитьРавенство(42, Json.Ответ); +КонецПроцедуры From 021d90f8bba1fec5a8562ee67acfd83781f7a292 Mon Sep 17 00:00:00 2001 From: Mr-Rm Date: Thu, 14 May 2026 13:12:16 +0400 Subject: [PATCH 4/4] null-safety; some cleanup; fix test --- .../Json/JSONReader.cs | 60 ++++--------------- tests/json/test-json_reader.os | 1 + 2 files changed, 12 insertions(+), 49 deletions(-) diff --git a/src/OneScript.StandardLibrary/Json/JSONReader.cs b/src/OneScript.StandardLibrary/Json/JSONReader.cs index 18ae4a365..866cd54b9 100644 --- a/src/OneScript.StandardLibrary/Json/JSONReader.cs +++ b/src/OneScript.StandardLibrary/Json/JSONReader.cs @@ -41,7 +41,6 @@ public override bool Read() } /// - /// /// Предназначен для последовательного чтения JSON-данных из файла или строки. /// [ContextClass("ЧтениеJSON", "JSONReader")] @@ -51,7 +50,6 @@ public class JSONReader : AutoContext private JsonReaderInternal _reader; /// - /// /// Возвращает true если для объекта чтения json был задан текст для парсинга. /// private bool IsOpen() => _reader != null; @@ -72,49 +70,25 @@ public static JSONReader Constructor() } /// - /// /// Указывает на позицию, находящуюся сразу после прочитанного значения. /// При ошибке чтение остается на позиции последнего успешно считанного символа. /// /// Число (Number), Неопределено (Undefined) [ContextProperty("ТекущаяПозиция", "CurrentPosition")] public IValue CurrentPosition - { - get - { - if (IsOpen()) - { - return ValueFactory.Create(_reader.LinePosition); - } - - return ValueFactory.Create(); // Неопределено - } - } + => IsOpen() ? ValueFactory.Create(_reader.LinePosition) : ValueFactory.Create(); /// - /// /// Указывает на позицию сразу после прочитанного значения. /// Например, перед чтением первого элемента - 0, после чтения первого элемента -1 . /// /// Число (Number), Неопределено (Undefined) [ContextProperty("ТекущаяСтрока", "CurrentLine")] public IValue CurrentLine - { - get - { - if (IsOpen()) - { - return ValueFactory.Create(_reader.LineNumber); - } - - return ValueFactory.Create(); // Неопределено - } - } + => IsOpen() ? ValueFactory.Create(_reader.LineNumber) : ValueFactory.Create(); /// - /// /// Содержит текущее значение: - /// /// - Число - если ТипТекущегоЗначения имеет значение Число; /// - Строка - если ТипТекущегоЗначения имеет одно из следующих значений: /// - Комментарий, @@ -161,7 +135,6 @@ public IValue CurrentValue default: throw JSONReaderException.CannotGetValue(); - ; } } } @@ -169,7 +142,6 @@ public IValue CurrentValue public object ReaderValue => _reader.Value; /// - /// /// Тип текущего значения в документе JSON во внутреннем формате. /// null - если чтение еще не началось или достигнут конец файла. /// @@ -184,7 +156,6 @@ public JsonToken CurrentJsonTokenType } /// - /// /// Тип текущего значения в документе JSON. /// Неопределено - если чтение еще не началось или достигнут конец файла. /// @@ -218,10 +189,8 @@ public JSONValueTypeEnum CurrentValueType } /// - /// /// Завершает чтение текста JSON из файла или строки. /// - /// [ContextMethod("Закрыть", "Close")] public void Close() { @@ -233,10 +202,10 @@ public void Close() } /// - /// - /// Открывает JSON-файл для чтения данным объектом. Если перед вызовом данного метода уже производилось чтение JSON из другого файла или строки, то чтение прекращается и объект инициализируется для чтения из указанного файла. + /// Открывает JSON-файл для чтения данным объектом. + /// Если перед вызовом данного метода уже производилось чтение JSON из другого файла или строки, + /// то чтение прекращается и объект инициализируется для чтения из указанного файла. /// - /// /// /// Имя файла, содержащего текст JSON. /// @@ -249,11 +218,9 @@ public void OpenFile(string JSONFileName, IValue encoding = null) StreamReader _fileReader; try - { - if (encoding != null) - _fileReader = FileOpener.OpenReader(JSONFileName, TextEncodingEnum.GetEncoding(encoding)); - else - _fileReader = FileOpener.OpenReader(JSONFileName, System.Text.Encoding.UTF8); + { + var enc = encoding != null ? TextEncodingEnum.GetEncoding(encoding) : System.Text.Encoding.UTF8; + _fileReader = FileOpener.OpenReader(JSONFileName, enc); } catch (Exception e) { @@ -280,7 +247,9 @@ public void OpenStream(IStreamWrapper streamContext, IValue encoding = null) { Close(); - var stream = streamContext.GetUnderlyingStream(); + var stream = streamContext?.GetUnderlyingStream() + ?? throw new ArgumentNullException(nameof(streamContext)); + var enc = encoding != null ? TextEncodingEnum.GetEncoding(encoding) : System.Text.Encoding.UTF8; _reader = new JsonReaderInternal(new StreamReader(stream, enc, leaveOpen:true)) @@ -293,7 +262,6 @@ public void OpenStream(IStreamWrapper streamContext, IValue encoding = null) /// Если текущее значение – начало массива или объекта, то пропускает его содержимое и конец. /// Для остальных типов значений работает аналогично методу Прочитать(). /// - /// [ContextMethod("Пропустить", "Skip")] public bool Skip() { @@ -310,24 +278,18 @@ public bool Skip() /// /// Выполняет чтение значения JSON. /// - /// [ContextMethod("Прочитать", "Read")] public bool Read() { CheckIfOpen(); return _reader.Read(); - } /// - /// /// Устанавливает строку, содержащую текст JSON для чтения данным объектом. Если перед вызовом данного метода уже производилось чтение JSON из другого файла или строки, то чтение прекращается и объект инициализируется для чтения из указанной строки. /// - /// /// /// Строка, содержащая текст в формате JSON. - /// - /// [ContextMethod("УстановитьСтроку", "SetString")] public void SetString(string JSONString) { diff --git a/tests/json/test-json_reader.os b/tests/json/test-json_reader.os index 4a7cdf8b3..fdc3b5dc5 100644 --- a/tests/json/test-json_reader.os +++ b/tests/json/test-json_reader.os @@ -249,6 +249,7 @@ БДД = ПолучитьБуферДвоичныхДанныхИзСтроки("{""ответ"":42}"); Поток = Новый ПотокВПамяти(БДД); Чтение = Новый ЧтениеJSON; + Чтение.ОткрытьПоток(Поток); Чтение.Закрыть(); Чтение.ОткрытьПоток(Поток); // Поток должен остаться открытым Json = ПрочитатьJSON(Чтение);