আমি এমন একটি রেইজেক্স সন্ধান করছি যা আমাকে জসনকে বৈধতা দেওয়ার অনুমতি দেয়।
আমি রেগেক্সের কাছে খুব নতুন এবং আমি যথেষ্ট জানি যে রেইজেক্সের সাথে পার্সিং খারাপ, তবে এটি যাচাই করতে ব্যবহৃত হতে পারে?
আমি এমন একটি রেইজেক্স সন্ধান করছি যা আমাকে জসনকে বৈধতা দেওয়ার অনুমতি দেয়।
আমি রেগেক্সের কাছে খুব নতুন এবং আমি যথেষ্ট জানি যে রেইজেক্সের সাথে পার্সিং খারাপ, তবে এটি যাচাই করতে ব্যবহৃত হতে পারে?
উত্তর:
বেশিরভাগ আধুনিক রেজেক্স বাস্তবায়ন পুনরাবৃত্তিমূলক পুনর্বিবেগগুলির জন্য মঞ্জুরি দেয়, যা একটি সম্পূর্ণ JSON ক্রমিক কাঠামো যাচাই করতে পারে। Json.org স্পেসিফিকেশন এটা বেশ সহজবোধ্য করে তোলে।
$pcre_regex = '
/
(?(DEFINE)
(?<number> -? (?= [1-9]|0(?!\d) ) \d+ (\.\d+)? ([eE] [+-]? \d+)? )
(?<boolean> true | false | null )
(?<string> " ([^"\\\\]* | \\\\ ["\\\\bfnrt\/] | \\\\ u [0-9a-f]{4} )* " )
(?<array> \[ (?: (?&json) (?: , (?&json) )* )? \s* \] )
(?<pair> \s* (?&string) \s* : (?&json) )
(?<object> \{ (?: (?&pair) (?: , (?&pair) )* )? \s* \} )
(?<json> \s* (?: (?&number) | (?&boolean) | (?&string) | (?&array) | (?&object) ) \s* )
)
\A (?&json) \Z
/six
';
এটি পিসিআরই ফাংশনগুলির সাথে পিএইচপিতে বেশ ভাল কাজ করে । পার্লে অশোধিত কাজ করা উচিত; এবং অবশ্যই অন্যান্য ভাষার জন্য মানিয়ে নেওয়া যেতে পারে। এছাড়াও এটি JSON পরীক্ষার ক্ষেত্রে সফল হয় ।
একটি সহজ পদ্ধতির হ'ল আরএফসি 4627, বিভাগ 6 এ উল্লিখিত ন্যূনতম ধারাবাহিকতা পরীক্ষা করা । তবে এটি কেবল সুরক্ষা পরীক্ষা এবং মৌলিক অ-বৈধতা সতর্কতা হিসাবে লক্ষ্য করা হচ্ছে:
var my_JSON_object = !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(
text.replace(/"(\\.|[^"\\])*"/g, ''))) &&
eval('(' + text + ')');
false
শীর্ষ স্তরের জেএসওএন মানটি একটি অ্যারে বা কোনও অবজেক্ট হতে হবে যখন একক আক্ষরিক মিল রয়েছে। এটিতে স্ট্রিং বা স্পেসে অনুমোদিত অক্ষর সেটগুলির অনেকগুলি সমস্যা রয়েছে।
হ্যাঁ, এটি একটি সাধারণ ভুল ধারণা যে নিয়মিত প্রকাশগুলি কেবল নিয়মিত ভাষার সাথেই মেলে । আসলে, পিসিআরই ফাংশনগুলি নিয়মিত ভাষার তুলনায় অনেক বেশি মেলাতে পারে, তারা কিছু অ-প্রসঙ্গ-মুক্ত ভাষাও মেলাতে পারে! RegExps এ উইকিপিডিয়ায় নিবন্ধটি সম্পর্কে একটি বিশেষ বিভাগ রয়েছে।
জেসন বিভিন্নভাবে পিসিআরই ব্যবহার করে স্বীকৃতি পেতে পারে! @ মারিও নামকৃত সাবপ্যাটার্ন এবং ব্যাক-রেফারেন্স ব্যবহার করে একটি দুর্দান্ত সমাধান দেখিয়েছে । তারপরে তিনি উল্লেখ করেছিলেন যে পুনরাবৃত্ত নিদর্শনগুলি ব্যবহার করে একটি সমাধান হওয়া উচিত (?R)
। এখানে পিএইচপি-তে লিখিত এই জাতীয় রিজ এক্সপের উদাহরণ রয়েছে:
$regexString = '"([^"\\\\]*|\\\\["\\\\bfnrt\/]|\\\\u[0-9a-f]{4})*"';
$regexNumber = '-?(?=[1-9]|0(?!\d))\d+(\.\d+)?([eE][+-]?\d+)?';
$regexBoolean= 'true|false|null'; // these are actually copied from Mario's answer
$regex = '/\A('.$regexString.'|'.$regexNumber.'|'.$regexBoolean.'|'; //string, number, boolean
$regex.= '\[(?:(?1)(?:,(?1))*)?\s*\]|'; //arrays
$regex.= '\{(?:\s*'.$regexString.'\s*:(?1)(?:,\s*'.$regexString.'\s*:(?1))*)?\s*\}'; //objects
$regex.= ')\Z/is';
আমি এর (?1)
পরিবর্তে ব্যবহার করছি (?R)
কারণ পরেরটি পুরো প্যাটার্নটির উল্লেখ করে তবে আমাদের রয়েছে \A
এবং \Z
সিকোয়েন্সগুলি সাবপ্যাটার্নগুলির অভ্যন্তরে ব্যবহার করা উচিত নয়। (?1)
বাইরেরতম বন্ধনী দ্বারা চিহ্নিত রেজিএক্সপ্যাক্সের উল্লেখ (এই কারণেই বহিরাগত থেকে ( )
শুরু হয় না ?:
)। সুতরাং, RegExp 268 টি অক্ষর দীর্ঘ হয় :)
/\A("([^"\\]*|\\["\\bfnrt\/]|\\u[0-9a-f]{4})*"|-?(?=[1-9]|0(?!\d))\d+(\.\d+)?([eE][+-]?\d+)?|true|false|null|\[(?:(?1)(?:,(?1))*)?\s*\]|\{(?:\s*"([^"\\]*|\\["\\bfnrt\/]|\\u[0-9a-f]{4})*"\s*:(?1)(?:,\s*"([^"\\]*|\\["\\bfnrt\/]|\\u[0-9a-f]{4})*"\s*:(?1))*)?\s*\})\Z/is
যাইহোক, এটি একটি "প্রযুক্তি প্রদর্শনের" হিসাবে বিবেচনা করা উচিত, ব্যবহারিক সমাধান হিসাবে নয়। পিএইচপি-তে আমি json_decode()
ফাংশনটি কল করার সাথে জেএসএন স্ট্রিংকে বৈধতা দেব (ঠিক যেমন @ এপিসিলন উল্লেখ করেছেন)। যদি আমি সেই জেএসওএন ব্যবহার করতে যাচ্ছি (যদি এটি বৈধ হয়) তবে এটি সেরা পদ্ধতি best
\d
করা বিপজ্জনক। অনেক রিজেপ্সে বাস্তবায়নের \d
সাথে এমন একটি অঙ্কের ইউনিকোড সংজ্ঞা মেলে যা কেবল নয় [0-9]
বরং পরিবর্তে বিকল্প স্ক্রিপ্টগুলিও অন্তর্ভুক্ত করে।
\d
হয় পিএইচপি এর পিসিআরই বাস্তবায়নে ইউনিকোড সংখ্যার সাথে মেলে না। উদাহরণস্বরূপ ٩
প্রতীক (0x669 আরবি -ভারতীয় অঙ্ক নয়টি) প্যাটার্ন ব্যবহার মেলানো হবে #\p{Nd}#u
কিন্তু#\d#u
/u
পতাকা ব্যবহার করেন নি বলে এটি হয় না । জেএসএনটি ইউটিএফ -8 এ এনকোড করা আছে। সঠিক রেজিপ্স্পের জন্য আপনার পতাকাটি ব্যবহার করা উচিত।
u
, দয়া করে আমার আগের মন্তব্যে নিদর্শনগুলি আবার দেখুন: স্ট্রিংস, সংখ্যা এবং বুলিয়ান সঠিকভাবে শীর্ষ স্তরের সাথে মেলে। আপনি দীর্ঘ regexp এখানে আটকে দিতে পারেন quanetic.com/Regex এবং নিজেকে চেষ্টা
JSON (নেস্টেড-এস {...}
) এর পুনরাবৃত্ত প্রকৃতির কারণে , রেজেক্স এটি বৈধ করার পক্ষে উপযুক্ত নয়। অবশ্যই, কিছু রিজেক্স স্বাদগুলি পুনরাবৃত্তভাবে প্যাটার্নগুলি * (এবং এর জন্য জেএসওনের সাথে মেলে থাকতে পারে) মেলাতে পারে তবে ফলাফলগুলি নিখরচায় দেখতে ভীতিজনক এবং প্রযোজনা আইএমওতে কখনও ব্যবহার করা উচিত নয়!
* সাবধান যদিও অনেক Regex বাস্তবায়নের না না রিকার্সিভ নিদর্শন সমর্থন করি। জনপ্রিয় প্রোগ্রামিং ল্যাঙ্গুয়েজগুলির মধ্যে, এগুলি রিকার্সিভ প্যাটার্নগুলি সমর্থন করে: পার্ল,। নেট, পিএইচপি এবং রুবি ১.৯.২
আমি @ মারিওর উত্তরটি চেষ্টা করেছি, তবে এটি আমার পক্ষে কার্যকর হয়নি, কারণ আমি জেএসওএন.আর.জি. ( সংরক্ষণাগার ) থেকে পরীক্ষার স্যুট ডাউনলোড করেছি এবং সেখানে 4 টি ব্যর্থ পরীক্ষা (ফেল 1.json, ফেল 18.json, ফেল 25.json, ফেল 27) রয়েছে। json)।
আমি ত্রুটিগুলি তদন্ত করেছি এবং খুঁজে পেয়েছি, এটি fail1.json
আসলে সঠিক (ম্যানুয়াল নোট এবং আরএফসি -7159 বৈধ স্ট্রিং অনুযায়ী একটি বৈধ জেএসওএনও রয়েছে)। ফাইলটিও fail18.json
কেস ছিল না, কারণ এটিতে গভীরভাবে-ঘরোয়া জেএসওএন রয়েছে contains
[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]
সুতরাং দুটি ফাইল বাকি: fail25.json
এবং fail27.json
:
[" tab character in string "]
এবং
["line
break"]
দুটিতেই অবৈধ অক্ষর রয়েছে। সুতরাং আমি এর মতো প্যাটার্নটি আপডেট করেছি (স্ট্রিং সাবপ্যাটার্ন আপডেট হয়েছে):
$pcreRegex = '/
(?(DEFINE)
(?<number> -? (?= [1-9]|0(?!\d) ) \d+ (\.\d+)? ([eE] [+-]? \d+)? )
(?<boolean> true | false | null )
(?<string> " ([^"\n\r\t\\\\]* | \\\\ ["\\\\bfnrt\/] | \\\\ u [0-9a-f]{4} )* " )
(?<array> \[ (?: (?&json) (?: , (?&json) )* )? \s* \] )
(?<pair> \s* (?&string) \s* : (?&json) )
(?<object> \{ (?: (?&pair) (?: , (?&pair) )* )? \s* \} )
(?<json> \s* (?: (?&number) | (?&boolean) | (?&string) | (?&array) | (?&object) ) \s* )
)
\A (?&json) \Z
/six';
সুতরাং এখন json.org থেকে সমস্ত আইনী পরীক্ষা পাস করা যেতে পারে।
ডকুমেন্টেশন এ খুঁজছি তাদেরকে JSON , মনে হয় যে Regex কেবল তিনটি অংশ হতে পারে লক্ষ্য ফিটনেস পরীক্ষা করার জন্য ঠিক হয়:
[]
বা{}
[{\[]{1}
...[}\]]{1}
[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]
...""
".*?"
...সব একসাথে:
[{\[]{1}([,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]|".*?")+[}\]]{1}
যদি জেএসএন স্ট্রিংয়ে newline
অক্ষর থাকে, তবে singleline
আপনার রেগেক্স স্বাদে স্যুইচটি ব্যবহার করা উচিত যাতে এটি .
মেলে newline
। দয়া করে মনে রাখবেন যে এটি সমস্ত খারাপ JSON এ ব্যর্থ হবে না, তবে এটি ব্যর্থ হবে যদি মৌলিক JSON কাঠামোটি অবৈধ হয়, যা পার্সারে যাওয়ার আগে একটি বেসিক স্যানিটি বৈধতা দেওয়ার সোজা-সামনের উপায়।
আমি মারিওর সমাধানটির একটি রুবি বাস্তবায়ন তৈরি করেছি, যা কাজ করে:
# encoding: utf-8
module Constants
JSON_VALIDATOR_RE = /(
# define subtypes and build up the json syntax, BNF-grammar-style
# The {0} is a hack to simply define them as named groups here but not match on them yet
# I added some atomic grouping to prevent catastrophic backtracking on invalid inputs
(?<number> -?(?=[1-9]|0(?!\d))\d+(\.\d+)?([eE][+-]?\d+)?){0}
(?<boolean> true | false | null ){0}
(?<string> " (?>[^"\\\\]* | \\\\ ["\\\\bfnrt\/] | \\\\ u [0-9a-f]{4} )* " ){0}
(?<array> \[ (?> \g<json> (?: , \g<json> )* )? \s* \] ){0}
(?<pair> \s* \g<string> \s* : \g<json> ){0}
(?<object> \{ (?> \g<pair> (?: , \g<pair> )* )? \s* \} ){0}
(?<json> \s* (?> \g<number> | \g<boolean> | \g<string> | \g<array> | \g<object> ) \s* ){0}
)
\A \g<json> \Z
/uix
end
########## inline test running
if __FILE__==$PROGRAM_NAME
# support
class String
def unindent
gsub(/^#{scan(/^(?!\n)\s*/).min_by{|l|l.length}}/u, "")
end
end
require 'test/unit' unless defined? Test::Unit
class JsonValidationTest < Test::Unit::TestCase
include Constants
def setup
end
def test_json_validator_simple_string
assert_not_nil %s[ {"somedata": 5 }].match(JSON_VALIDATOR_RE)
end
def test_json_validator_deep_string
long_json = <<-JSON.unindent
{
"glossary": {
"title": "example glossary",
"GlossDiv": {
"id": 1918723,
"boolean": true,
"title": "S",
"GlossList": {
"GlossEntry": {
"ID": "SGML",
"SortAs": "SGML",
"GlossTerm": "Standard Generalized Markup Language",
"Acronym": "SGML",
"Abbrev": "ISO 8879:1986",
"GlossDef": {
"para": "A meta-markup language, used to create markup languages such as DocBook.",
"GlossSeeAlso": ["GML", "XML"]
},
"GlossSee": "markup"
}
}
}
}
}
JSON
assert_not_nil long_json.match(JSON_VALIDATOR_RE)
end
end
end
"স্ট্রিং এবং সংখ্যা" এর জন্য, আমি মনে করি যে সংখ্যাগুলির জন্য আংশিক নিয়মিত প্রকাশ:
-?(?:0|[1-9]\d*)(?:\.\d+)(?:[eE][+-]\d+)?
পরিবর্তে হওয়া উচিত:
-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+\-]?\d+)?
যেহেতু সংখ্যার দশমিক অংশটি alচ্ছিক, এবং এটি সম্ভবত -
প্রতীকটি থেকে বাঁচতে নিরাপদ [+-]
কারণ এটি বন্ধনীগুলির মধ্যে একটি বিশেষ অর্থ রয়েছে
\d
করা বিপজ্জনক। অনেক রিজেপ্সে বাস্তবায়নের \d
সাথে এমন একটি অঙ্কের ইউনিকোড সংজ্ঞা মেলে যা কেবল নয় [0-9]
বরং পরিবর্তে বিকল্প স্ক্রিপ্টগুলিও অন্তর্ভুক্ত করে।
একটি JSON অ্যারেতে একটি পিছনে থাকা কমাটি আমার পার্ল 5.16 কে ঝুলিয়ে দিয়েছে, সম্ভবত কারণ এটি ব্যাকট্র্যাক করে চলেছে। আমাকে ব্যাকট্র্যাক-টার্মিনেটিং নির্দেশিকা যুক্ত করতে হয়েছিল:
(?<json> \s* (?: (?&number) | (?&boolean) | (?&string) | (?&array) | (?&object) )(*PRUNE) \s* )
^^^^^^^^
এইভাবে, এটি একবার এমন কোনও কনস্ট্রাক্ট সনাক্ত করে যা 'alচ্ছিক' ( *
বা ?
) নয়, এটি অন্য কিছু হিসাবে চিহ্নিত করার চেষ্টা করা উচিত নয়।
যেমনটি উপরে লেখা হয়েছিল, আপনি যে ভাষাটি ব্যবহার করেন তাতে যদি JSON- গ্রন্থাগার আসে তবে স্ট্রিংটি ডিকোড করার চেষ্টা করুন এবং ব্যর্থ হলে ব্যতিক্রম / ত্রুটি ধরুন! যদি ভাষাটি না করে (কেবলমাত্র ফ্রিমার্কারের সাথে এরকম কেস থাকে) তবে নিম্নলিখিত রেজেক্সটি কমপক্ষে কিছু খুব প্রাথমিক বৈধতা সরবরাহ করতে পারে (এটি পিএইচপি / পিসিআরই আরও ব্যবহারকারীদের জন্য পরীক্ষামূলক / ব্যবহারযোগ্য হওয়ার জন্য লেখা)। এটি গৃহীত সমাধানের মতো নির্বোধ নয়, তবে এটি ভীতিজনকও নয়)):
~^\{\s*\".*\}$|^\[\n?\{\s*\".*\}\n?\]$~s
সংক্ষিপ্ত ব্যাখ্যা:
// we have two possibilities in case the string is JSON
// 1. the string passed is "just" a JSON object, e.g. {"item": [], "anotheritem": "content"}
// this can be matched by the following regex which makes sure there is at least a {" at the
// beginning of the string and a } at the end of the string, whatever is inbetween is not checked!
^\{\s*\".*\}$
// OR (character "|" in the regex pattern)
// 2. the string passed is a JSON array, e.g. [{"item": "value"}, {"item": "value"}]
// which would be matched by the second part of the pattern above
^\[\n?\{\s*\".*\}\n?\]$
// the s modifier is used to make "." also match newline characters (can happen in prettyfied JSON)
যদি আমি এমন কিছু মিস করি যা এটি অনিচ্ছাকৃতভাবে ভেঙে দেয় তবে আমি মন্তব্যের জন্য কৃতজ্ঞ!
এটি কী (স্ট্রিং) যাচাই করে: মান (স্ট্রিং, পূর্ণসংখ্যা, [{কী: মান}, {কী: মান}], {কী: মান})
^\{(\s|\n\s)*(("\w*"):(\s)*("\w*"|\d*|(\{(\s|\n\s)*(("\w*"):(\s)*("\w*(,\w+)*"|\d{1,}|\[(\s|\n\s)*(\{(\s|\n\s)*(("\w*"):(\s)*(("\w*"|\d{1,}))((,(\s|\n\s)*"\w*"):(\s)*("\w*"|\d{1,}))*(\s|\n)*\})){1}(\s|\n\s)*(,(\s|\n\s)*\{(\s|\n\s)*(("\w*"):(\s)*(("\w*"|\d{1,}))((,(\s|\n\s)*"\w*"):(\s)*("\w*"|\d{1,}))*(\s|\n)*\})?)*(\s|\n\s)*\]))((,(\s|\n\s)*"\w*"):(\s)*("\w*(,\w+)*"|\d{1,}|\[(\s|\n\s)*(\{(\s|\n\s)*(("\w*"):(\s)*(("\w*"|\d{1,}))((,(\s|\n\s)*"\w*"):(\s)*("\w*"|\d{1,}))*(\s|\n)*\})){1}(\s|\n\s)*(,(\s|\n\s)*\{(\s|\n\s)*(("\w*"):(\s)*(("\w*"|\d{1,}))((,(\s|\n\s)*"\w*"):("\w*"|\d{1,}))*(\s|\n)*\})?)*(\s|\n\s)*\]))*(\s|\n\s)*\}){1}))((,(\s|\n\s)*"\w*"):(\s)*("\w*"|\d*|(\{(\s|\n\s)*(("\w*"):(\s)*("\w*(,\w+)*"|\d{1,}|\[(\s|\n\s)*(\{(\s|\n\s)*(("\w*"):(\s)*(("\w*"|\d{1,}))((,(\s|\n\s)*"\w*"):(\s)*("\w*"|\d{1,}))*(\s|\n)*\})){1}(\s|\n\s)*(,(\s|\n\s)*\{(\s|\n\s)*(("\w*"):(\s)*(("\w*"|\d{1,}))((,(\s|\n\s)*"\w*"):(\s)*("\w*"|\d{1,}))*(\s|\n)*\})?)*(\s|\n\s)*\]))((,(\s|\n\s)*"\w*"):(\s)*("\w*(,\w+)*"|\d{1,}|\[(\s|\n\s)*(\{(\s|\n\s)*(("\w*"):(\s)*(("\w*"|\d{1,}))((,(\s|\n\s)*"\w*"):(\s)*("\w*"|\d{1,}))*(\s|\n)*\})){1}(\s|\n\s)*(,(\s|\n\s)*\{(\s|\n\s)*(("\w*"):(\s)*(("\w*"|\d{1,}))((,(\s|\n\s)*"\w*"):("\w*"|\d{1,}))*(\s|\n)*\})?)*(\s|\n\s)*\]))*(\s|\n\s)*\}){1}))*(\s|\n)*\}$
{
"key":"string",
"key": 56,
"key":{
"attr":"integer",
"attr": 12
},
"key":{
"key":[
{
"attr": 4,
"attr": "string"
}
]
}
}
এখানে বৈধতা স্ট্রিং জন্য আমার regexp:
^\"([^\"\\]*|\\(["\\\/bfnrt]{1}|u[a-f0-9]{4}))*\"$
মূল সিনট্যাক্স ডায়াগ্রাম usign লেখা ছিল ।