Skip to content

Commit

Permalink
Полностью переделан ПрочитатьJSON по issue EvilBeaver#1373 и работе с…
Browse files Browse the repository at this point in the history
… объектами +тесты
  • Loading branch information
Mr-Rm committed Oct 31, 2023
1 parent 69e5c3b commit 89d18e5
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 109 deletions.
196 changes: 98 additions & 98 deletions src/ScriptEngine.HostedScript/Library/Json/GlobalJsonFunctions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,132 +55,132 @@ public static IAttachableContext CreateInstance()
[ContextMethod("ПрочитатьJSON", "ReadJSON")]
public IValue ReadJSON(JSONReader Reader, bool ReadToMap = false, IValue PropertiesWithDateValuesNames = null, IValue ExpectedDateFormat = null, string ReviverFunctionName = null, IValue ReviverFunctionModule = null, IValue ReviverFunctionAdditionalParameters = null, IValue RetriverPropertiesNames = null, int MaximumNesting = 500)
{
if (ReadToMap)
return ReadJSONInMap(Reader);
else
return ReadJSONInStruct(Reader);
var jsonReader = new JsonReaderInternal(Reader);
return ReadToMap ? jsonReader.Read<MapImpl>() : jsonReader.Read<StructureImpl>();
}

public IValue ReadJSONInStruct(JSONReader Reader, bool nestedArray = false)
internal class JsonReaderInternal
{
if (nestedArray)
{
ArrayImpl NestedArray = new ArrayImpl();

while (Reader.Read())
{
if (Reader.CurrentJsonTokenType == JsonToken.EndArray)
{
break;
}
else if (Reader.CurrentJsonTokenType == JsonToken.StartObject)
{
NestedArray.Add(ReadJSONInStruct(Reader));
}
else if (Reader.CurrentJsonTokenType == JsonToken.StartArray)
{
NestedArray.Add(ReadJSONInStruct(Reader, true));
}
else
NestedArray.Add(Reader.CurrentValue);
}
return NestedArray;
}

StructureImpl ResStruct = new StructureImpl();
private readonly JSONReader _reader;
private Func<IValue> _builder;
private Action<IValue, string, IValue> _inserter;

while ((Reader).Read())
private void Init<TStructure>()
{
if (Reader.CurrentJsonTokenType == JsonToken.PropertyName)
if (typeof(TStructure) == typeof(StructureImpl))
{
string PropertyName = Reader.CurrentValue.AsString();
Reader.Read();

if (Reader.CurrentJsonTokenType == JsonToken.StartObject)
{
ResStruct.Insert(PropertyName, ReadJSONInStruct(Reader));
}
else if (Reader.CurrentJsonTokenType == JsonToken.StartArray)
{
ResStruct.Insert(PropertyName, ReadJSONInStruct(Reader, true));
}
else
{
ResStruct.Insert(PropertyName, Reader.CurrentValue);
}
_builder = () => new StructureImpl();
_inserter = (o, s, v) => ((StructureImpl)o).Insert(s, v);
}
else if (Reader.CurrentJsonTokenType == JsonToken.EndObject)
else if (typeof(TStructure) == typeof(MapImpl))
{
break;
_builder = () => new MapImpl();
_inserter = (o, s, v) =>((MapImpl)o).Insert(ValueFactory.Create(s), v);
}
else if (Reader.CurrentJsonTokenType == JsonToken.StartArray)
else
{
return ReadJSONInStruct(Reader, true);
throw new RuntimeException();
}
}
return ResStruct;
}
public JsonReaderInternal(JSONReader reader)
{
_reader = reader;
}

public IValue ReadJSONInMap(JSONReader Reader, bool nestedArray = false)
{
private IValue Create() => _builder();

if (nestedArray)
private void AddProperty(IValue obj, string str, IValue val) => _inserter(obj, str, val);

public IValue Read<T>()
{
ArrayImpl NestedArray = new ArrayImpl();
Init<T>();

while (Reader.Read())
try
{
if (ReadJsonValue(out var value))
return value;
}
catch (JsonReaderException)
{
if (Reader.CurrentJsonTokenType == JsonToken.EndArray)
{
break;
}
else if (Reader.CurrentJsonTokenType == JsonToken.StartObject)
{
NestedArray.Add(ReadJSONInMap(Reader));
}
else if (Reader.CurrentJsonTokenType == JsonToken.StartArray)
{
NestedArray.Add(ReadJSONInMap(Reader, true));
}
else
NestedArray.Add(Reader.CurrentValue);
}
return NestedArray;

throw InvalidJsonException();
}

MapImpl ResStruct = new MapImpl();
while ((Reader).Read())
private JsonToken ReadJsonToken()
{
if (Reader.CurrentJsonTokenType == JsonToken.PropertyName)
{
string PropertyName = Reader.CurrentValue.AsString();
Reader.Read();

if (Reader.CurrentJsonTokenType == JsonToken.StartObject)
{
ResStruct.Insert(ValueFactory.Create(PropertyName), ReadJSONInMap(Reader));
}
else if (Reader.CurrentJsonTokenType == JsonToken.StartArray)
{
ResStruct.Insert(ValueFactory.Create(PropertyName), ReadJSONInMap(Reader, true));
}
else
{
ResStruct.Insert(ValueFactory.Create(PropertyName), Reader.CurrentValue);
}
}
else if (Reader.CurrentJsonTokenType == JsonToken.EndObject)
while (_reader.Read())
{
break;
var tok = _reader.CurrentJsonTokenType;
if (tok != JsonToken.Comment)
return tok;
}
else if (Reader.CurrentJsonTokenType == JsonToken.StartArray)

return JsonToken.None;
}

private bool ReadJsonValue(out IValue value)
{
switch (ReadJsonToken())
{
return ReadJSONInMap(Reader, true);
case JsonToken.StartObject:
var jsonObject = Create();

while (ReadJsonToken() == JsonToken.PropertyName)
{
var propertyName = _reader.CurrentValue.AsString();
if (!ReadJsonValue(out value))
throw InvalidJsonException();

AddProperty(jsonObject, propertyName, value);
}

if (_reader.CurrentJsonTokenType == JsonToken.EndObject)
{
value = jsonObject;
return true;
}
break;

case JsonToken.StartArray:
var resArray = new ArrayImpl();

while (ReadJsonValue(out value))
{
resArray.Add(value);
}

if (_reader.CurrentJsonTokenType == JsonToken.EndArray)
{
value = resArray;
return true;
}
break;

case JsonToken.EndArray:
case JsonToken.EndObject:
case JsonToken.None:
break;

default:
value = _reader.CurrentValue;
return true;
}

value = null;
return false;
}

private RuntimeException InvalidJsonException()
{
return new RuntimeException(string.Format(Locale.NStr
("ru='Недопустимое состояние потока чтения JSON в строке {0} позиции {1}'"
+"en='Invalid JSON reader state at line {0} position {1}'"),
_reader.CurrentLine, _reader.CurrentPosition));
}
return ResStruct;
}


/// <summary>
///
/// Выполняет преобразование строки, прочитанной в JSON-формате, в значение типа Дата.
Expand Down
18 changes: 8 additions & 10 deletions src/ScriptEngine.HostedScript/Library/Json/JSONReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ public IValue CurrentPosition
else
return ValueFactory.Create(); // Неопределено
}

}


Expand All @@ -81,7 +80,6 @@ public IValue CurrentLine
else
return ValueFactory.Create(); // Неопределено
}

}


Expand Down Expand Up @@ -219,7 +217,6 @@ public IValue CurrentValueType
else
throw NotOpenException();
}

}

/// <summary>
Expand All @@ -232,7 +229,6 @@ public IValue CurrentValueType
[ContextMethod("Закрыть", "Close")]
public void Close()
{

if (_reader != null)
{
_reader.Close();
Expand Down Expand Up @@ -271,8 +267,10 @@ public void OpenFile(string JSONFileName, IValue encoding = null)
throw new RuntimeException(e.Message, e);
}

_reader = new JsonTextReader(_fileReader);

_reader = new JsonTextReader(_fileReader)
{
SupportMultipleContent = true
};
}


Expand Down Expand Up @@ -309,7 +307,6 @@ public bool Skip()
}
else
throw NotOpenException();

}


Expand All @@ -321,7 +318,6 @@ public bool Skip()
public bool Read()
{
return _reader.Read();

}


Expand All @@ -340,7 +336,10 @@ public void SetString(string JSONString)
if (IsOpen())
Close();

_reader = new JsonTextReader(new StringReader(JSONString));
_reader = new JsonTextReader(new StringReader(JSONString))
{
SupportMultipleContent = true
};
}

RuntimeException NotOpenException()
Expand All @@ -354,6 +353,5 @@ RuntimeException CannotGetValueException()
return new RuntimeException(Locale.NStr
("ru='Текущее значение JSON не может быть получено';en='Cannot get current JSON value'"));
}

}
}
17 changes: 16 additions & 1 deletion tests/global-json.os
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
СписокТестов.Добавить("Тест_ДолженВызватьОшибку_ПриНезакрытомВложенномОбъекте");
СписокТестов.Добавить("Тест_ДолженВызватьОшибку_ПриПропущенномЗначенииСвойства");
СписокТестов.Добавить("Тест_ДолженВызватьОшибку_ПриНезакрытомКомментарии");
СписокТестов.Добавить("Тест_ДолженВызватьОшибку_ПриНедопустимомКлючеСтруктуры");
СписокТестов.Добавить("Тест_ДолженПроверить_ПроизвольныйКлючСоответствия");

Возврат СписокТестов;

Expand Down Expand Up @@ -221,7 +223,6 @@
КонецПроцедуры



Процедура Тест_ДолженВызватьОшибку_ПриНезакрытомМассиве() Экспорт
Текст = "[[[123,456]]";
Попытка
Expand Down Expand Up @@ -282,5 +283,19 @@
ВызватьИсключение "Должно было быть выдано исключение, но его не было";
КонецПроцедуры

Процедура Тест_ДолженВызватьОшибку_ПриНедопустимомКлючеСтруктуры() Экспорт
Текст = "{""123"":""456""}";
Попытка
Результат = ПрочитатьJSONИзСтроки(Текст);
Исключение
Возврат;
КонецПопытки;
ВызватьИсключение "Должно было быть выдано исключение, но его не было";
КонецПроцедуры

Процедура Тест_ДолженПроверить_ПроизвольныйКлючСоответствия() Экспорт
Текст = "{""%/$!"":""456""}";
Результат = ПрочитатьJSONИзСтроки(Текст, Истина);
юТест.ПроверитьРавенство("456", Результат["%/$!"]);
КонецПроцедуры

0 comments on commit 89d18e5

Please sign in to comment.