Browse Source

add TryNodeFromJsonString: ability to parse object and check errors without try-catch

ilnurkh 1 year ago
parent
commit
1761cf1700

+ 1 - 0
library/cpp/json/common/defs.cpp

@@ -62,6 +62,7 @@ bool TJsonCallbacks::OnEnd() {
 }
 
 void TJsonCallbacks::OnError(size_t off, TStringBuf reason) {
+    HaveErrors = true;
     if (ThrowException) {
         ythrow TJsonException() << "JSON error at offset " << off << " (" << reason << ")";
     }

+ 4 - 0
library/cpp/json/common/defs.h

@@ -32,7 +32,11 @@ namespace NJson {
         virtual bool OnEnd();
         virtual void OnError(size_t off, TStringBuf reason);
 
+        bool GetHaveErrors() const {
+            return HaveErrors;
+        }
     protected:
         bool ThrowException;
+        bool HaveErrors = false;
     };
 }

+ 11 - 0
library/cpp/yson/node/node_io.cpp

@@ -126,6 +126,17 @@ void NodeToCanonicalYsonStream(const TNode& node, IOutputStream* output, NYson::
     visitor.Visit(node);
 }
 
+bool TryNodeFromJsonString(const TStringBuf input, TNode& dst)
+{
+    TMemoryInput stream(input);
+    TNodeBuilder builder(&dst);
+    TYson2JsonCallbacksAdapter callbacks(&builder, /*throwException*/ false);
+    NJson::TJsonReaderConfig config;
+    config.DontValidateUtf8 = true;
+    NJson::ReadJson(&stream, &config, &callbacks);
+    return !callbacks.GetHaveErrors();
+}
+
 TNode NodeFromJsonString(const TStringBuf input)
 {
     TMemoryInput stream(input);

+ 1 - 0
library/cpp/yson/node/node_io.h

@@ -31,6 +31,7 @@ void NodeToCanonicalYsonStream(const TNode& node, IOutputStream* output, ::NYson
 
 // Parse TNode from string in JSON format
 TNode NodeFromJsonString(const TStringBuf input);
+bool TryNodeFromJsonString(const TStringBuf input, TNode& dst);
 
 // Convert TJsonValue to TNode
 TNode NodeFromJsonValue(const ::NJson::TJsonValue& input);

+ 13 - 0
library/cpp/yson/node/node_ut.cpp

@@ -482,3 +482,16 @@ Y_UNIT_TEST_SUITE(YtNodeTest) {
         UNIT_ASSERT_VALUES_EQUAL(node.ChildAs<TString>(0), "yaddayadda");
     }
 }
+
+
+Y_UNIT_TEST_SUITE(YtNodeIoTest) {
+    Y_UNIT_TEST(FromJson) {
+        NYT::TNode node;
+        node = NYT::NodeFromJsonString("1");
+        UNIT_ASSERT_VALUES_EQUAL(node.ConvertTo<int>(), 1);
+        UNIT_ASSERT(!NYT::TryNodeFromJsonString("", node));
+        UNIT_ASSERT_VALUES_EQUAL(node.ConvertTo<int>(), 1);
+        UNIT_ASSERT_EXCEPTION(NYT::NodeFromJsonString(""), yexception);
+        UNIT_ASSERT_VALUES_EQUAL(node.ConvertTo<int>(), 1);
+    }
+}