/
EvilBeaver
/
OneScript
Обзор
Документация
Войти
/
EvilBeaver
/
OneScript
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
v2.0.0-RC3
src/OneScript.StandardLibrary/Json/JSONReader.cs
341 строка
13 KB
EvilBeaver
Выделена отдельная папка для инфраструктуры исключений
24 июл 2023, 22:46
24 июл 2023, 22:46
d1c2e94
Код
Авторство
О чём код?
/*---------------------------------------------------------- This Source Code Form is subject to the terms of the Mozilla Public License, v.2.0. If a copy of the MPL was not distributed with this file, You can obtain one 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.Text; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; namespace OneScript.StandardLibrary.Json { /// <summary> /// /// Предназначен для последовательного чтения JSON-данных из файла или строки. /// </summary> [ContextClass("ЧтениеJSON", "JSONReader")] public class JSONReader : AutoContext<JSONReader> { private JsonTextReader _reader; // Объект из библиотеки Newtonsoft для работы с форматом JSON /// <summary> /// /// Возвращает true если для объекта чтения json был задан текст для парсинга. /// </summary> private bool IsOpen() { return _reader != null; } public JSONReader() { } [ScriptConstructor] public static JSONReader Constructor() { return new JSONReader(); } /// <summary> /// /// Указывает на позицию, находящуюся сразу после прочитанного значения. /// При ошибке чтение остается на позиции последнего успешно считанного символа. /// </summary> /// <value>Число (Number), Неопределено (Undefined)</value> [ContextProperty("ТекущаяПозиция", "CurrentPosition")] public IValue CurrentPosition { get { if (IsOpen()) { return ValueFactory.Create(_reader.LinePosition); } else return ValueFactory.Create(); // Неопределено } } /// <summary> /// /// Указывает на позицию сразу после прочитанного значения. /// Например, перед чтением первого элемента - 0, после чтения первого элемента -1 . /// </summary> /// <value>Число (Number), Неопределено (Undefined)</value> [ContextProperty("ТекущаяСтрока", "CurrentLine")] public IValue CurrentLine { get { if (IsOpen()) { return ValueFactory.Create(_reader.LineNumber); } else return ValueFactory.Create(); // Неопределено } } /// <summary> /// /// Содержит текущее значение: /// /// - Число - если ТипТекущегоЗначения имеет значение Число; /// - Строка - если ТипТекущегоЗначения имеет значение: /// /// - Комментарий, /// - ИмяСвойства, /// - Строка; /// - Булево - если ТипТекущегоЗначения имеет значение Булево, /// - Неопределено - если ТипТекущегоЗначения имеет значение Null. /// Исключение генерируется в случае, если ТипТекущегоЗначения имеет одно из следующих значений: /// /// - НачалоМассива, /// - КонецМассива, /// - НачалоОбъекта, /// - КонецОбъекта, /// - Ничего. /// </summary> /// <value>Число (Number), Строка (String), Булево (Boolean), Неопределено (Undefined)</value> [ContextProperty("ТекущееЗначение", "CurrentValue")] public IValue CurrentValue { get { if (IsOpen()) { switch (_reader.TokenType) { case JsonToken.String: case JsonToken.Comment: case JsonToken.PropertyName: return ValueFactory.Create((string)_reader.Value); case JsonToken.Integer: case JsonToken.Float: return ValueFactory.Create(Convert.ToDecimal(_reader.Value)); case JsonToken.Boolean: return ValueFactory.Create((bool)_reader.Value); case JsonToken.Date: return ValueFactory.Create((DateTime)_reader.Value); case JsonToken.Null: case JsonToken.Undefined: return ValueFactory.Create(); default: throw CannotGetValueException(); } } else throw NotOpenException(); } } /// <summary> /// /// Тип текущего значения в документе JSON во внутреннем формате. /// null - если чтение еще не началось или достигнут конец файла. /// </summary> /// <value>CurrentJsonTokenType</value> public JsonToken CurrentJsonTokenType { get { if (IsOpen()) { return _reader.TokenType; } else throw NotOpenException(); } } /// <summary> /// /// Тип текущего значения в документе JSON. /// Неопределено - если чтение еще не началось или достигнут конец файла. /// </summary> /// <value>ТипЗначенияJSON (JSONValueType)</value> [ContextProperty("ТипТекущегоЗначения", "CurrentValueType")] public JSONValueTypeEnum CurrentValueType { get { if (IsOpen()) { return _reader.TokenType switch { JsonToken.Null => JSONValueTypeEnum.Null, JsonToken.Undefined => JSONValueTypeEnum.Null, JsonToken.StartObject => JSONValueTypeEnum.ObjectStart, JsonToken.StartArray => JSONValueTypeEnum.ArrayStart, JsonToken.PropertyName => JSONValueTypeEnum.PropertyName, JsonToken.Comment => JSONValueTypeEnum.Comment, JsonToken.Integer => JSONValueTypeEnum.Number, JsonToken.Float => JSONValueTypeEnum.Number, JsonToken.String => JSONValueTypeEnum.String, JsonToken.Boolean => JSONValueTypeEnum.Boolean, JsonToken.EndObject => JSONValueTypeEnum.ObjectEnd, JsonToken.EndArray => JSONValueTypeEnum.ArrayEnd, _ => JSONValueTypeEnum.None }; } else throw NotOpenException(); } } /// <summary> /// /// Завершает чтение текста JSON из файла или строки. /// </summary> /// /// /// [ContextMethod("Закрыть", "Close")] public void Close() { if (_reader != null) { _reader.Close(); _reader = null; } } /// <summary> /// /// Открывает JSON-файл для чтения данным объектом. Если перед вызовом данного метода уже производилось чтение JSON из другого файла или строки, то чтение прекращается и объект инициализируется для чтения из указанного файла. /// </summary> /// /// <param name="JSONFileName"> /// Имя файла, содержащего текст JSON. </param> /// <param name="encoding"> /// Позволяет задать кодировку входного файла.</param> [ContextMethod("ОткрытьФайл", "OpenFile")] public void OpenFile(string JSONFileName, IValue encoding = null) { if (IsOpen()) Close(); StreamReader _fileReader; try { if (encoding != null) _fileReader = FileOpener.OpenReader(JSONFileName, TextEncodingEnum.GetEncoding(encoding)); else _fileReader = FileOpener.OpenReader(JSONFileName, System.Text.Encoding.UTF8); } catch (Exception e) { throw new RuntimeException(e.Message, e); } _reader = new JsonTextReader(_fileReader); } /// <summary> /// Если текущее значение – начало массива или объекта, то пропускает его содержимое и конец. /// Для остальных типов значений работает аналогично методу Прочитать(). /// </summary> /// [ContextMethod("Пропустить", "Skip")] public bool Skip() { if (IsOpen()) { if (_reader.TokenType == JsonToken.StartArray || _reader.TokenType == JsonToken.StartObject) { while (_reader.Read()) { if (_reader.TokenType == JsonToken.EndArray || _reader.TokenType == JsonToken.EndObject) { return _reader.Read(); } } return true; } else { if (_reader.Read()) return _reader.Read(); else return false; } } else throw NotOpenException(); } /// <summary> /// Выполняет чтение значения JSON. /// </summary> /// [ContextMethod("Прочитать", "Read")] public bool Read() { return _reader.Read(); } /// <summary> /// /// Устанавливает строку, содержащую текст JSON для чтения данным объектом. Если перед вызовом данного метода уже производилось чтение JSON из другого файла или строки, то чтение прекращается и объект инициализируется для чтения из указанной строки. /// </summary> /// /// <param name="JSONString"> /// Строка, содержащая текст в формате JSON. </param> /// /// [ContextMethod("УстановитьСтроку", "SetString")] public void SetString(string JSONString) { if (IsOpen()) Close(); _reader = new JsonTextReader(new StringReader(JSONString)); } RuntimeException NotOpenException() { return new RuntimeException(Locale.NStr ("ru='Источник данных JSON не открыт'; en='JSON data source is not opened'")); } RuntimeException CannotGetValueException() { return new RuntimeException(Locale.NStr ("ru='Текущее значение JSON не может быть получено';en='Cannot get current JSON value'")); } } }