コード内にあるオブジェクト形式のデータに同名のkeyが使われていた場合について。
JavaScript側からこれらのキーを独自のものとして値を読み取る方法はあるのでしょうか?
Javascript
1{ 2"key1": "value1", 3"key2": "value2", 4"key1": "value3" 5}
コード(テキスト)としてはデータが残っているのですが、量が多くて人力でキーを修正していくのは困難です。
プレーンテキストを正規表現などを利用してオブジェクトに作り直す方法を思いつきましたが、他にも良い方法があれば教えて頂きたいです。
整形する方法はJavaScript以外でも大丈夫です。既存のツールなどがあればそちらを利用します。
よろしくお願いします。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2020/04/07 10:44
2020/04/07 21:28
回答5件
0
ベストアンサー
それはJSONとしておかしいので、
まともな方法で値を取り出す事は不可能です。
データクレンジングを行い妥当なJSONに整形しなければ読み書きできません
では早速やっていきましょう。
基本的には改行コードを全て潰して1行の文字列に潰してしまうのが楽でしょう。
※ただし、""
等の文字列に囲まれたエリアで改行やカンマ等の文字を扱っている場合は高度なエスケープ処理が出来るので、1文字ずつ取得していくやり方が必要になります。
js
1const json = `{ 2'key1': value1, 3'key2': value2, 4'key1': value3 5}`; 6 7console.log( 8 json.replace(/\r?\n/g, "") 9); 10// "{'key1': value1,'key2': value2,'key1': value3}" 11 12console.log( 13 json 14 .replace(/\r?\n/g, "") 15 .trim() // trimで文字列前後のホワイトスペースを削除して 16 .slice(1, -1) // 先頭と末尾の文字を捨てて{}の中身を抽出 17 .split(",") // カンマで切って配列化 18); 19// ["'key1': value1", "'key2': value2", "'key1': value3"]
ここで配列になるので、今度はfor..of文で加工していきましょう。
js
1const json = `{ 2'key1': value1, 3'key2': value2, 4'key1': value3 5}`; 6 7const data = json 8 .replace(/\r?\n/g, "") 9 .trim() 10 .slice(1, -1) 11 .split(","); 12 13const result = []; 14for (const datum of data) { 15 // datum = "'key1': value1" 16 const [key, val] = datum.split(":").map(it => it.trim()); 17 result.push({key, val}); 18} 19console.log(result);
json
1[ 2 { 3 "key": "'key1'", 4 "val": "value1" 5 }, 6 { 7 "key": "'key2'", 8 "val": "value2" 9 }, 10 { 11 "key": "'key1'", 12 "val": "value3" 13 } 14]
key値が"'key1'"
みたいになっていますが、
先頭の文字を取り出してチェックしてシングルクォートだとわかるなら
最初と最後の文字を切り飛ばすようにしていけばすすめると思います。
投稿2020/04/07 10:42
総合スコア21203
0
Symbol
にできるならワンチャンあるかも
js
1const o = { 2[Symbol('key1')]: "value1", 3[Symbol('key2')]: "value2", 4[Symbol('key1')]: "value3" 5}; 6 7Object.getOwnPropertySymbols(o).length //3
投稿2020/04/07 10:42
総合スコア36960
0
こんにちは
この回答では、パイプでつなぐことを意図した、以下の2つのコマンドライン用スクリプトを作ります。
(1) data2xml: 標準入力から、ご質問に提示されている形式の、以下のようなテキストを受け取り、等価な情報を持つXMLを作って標準出力に表示する。
plain
1{ 2'key1': value1, 3'key2': value2, 4'key1': value3 5}
(2) xml2json: 標準入力からXMLを受け取って、JSONに変換にして標準出力に表示する。
ご質問に
整形する方法はJavaScript以外でも大丈夫です。
とありましたので、Python で書きました。
$ python -V
Python 3.7.4
$ cat data.txt
plain
1{ 2'key1': value1, 3'key2': value2, 4'key1': value3 5}
$ cat data2xml.py
python3
1import sys 2import re 3 4for line in sys.stdin: 5 s = line.strip() 6 7 if s == '{': 8 print('<?xml version="1.0" encoding="UTF-8" ?>\n<data>') 9 elif s == '}': 10 print('</data>') 11 else: 12 m = re.search(r'\'(\w+)\':\s+(\w+)', s) 13 if m: 14 k, v = m.group(1), m.group(2) 15 print(f'<{k}>{v}</{k}>')
$ cat data.txt | python data2xml.py
xml
1<?xml version="1.0" encoding="UTF-8" ?> 2<data> 3<key1>value1</key1> 4<key2>value2</key2> 5<key1>value3</key1> 6</data>
$ pip install lxml xmljson
Collecting lxml
Using cached https://files.pythonhosted.org/packages/a7/85/8b1a9a33b451114e352c29a200320f086ea30ff163599dd39cb627e7c86a/lxml-4.5.0-cp37-cp37m-macosx_10_9_x86_64.whl
Collecting xmljson
Using cached https://files.pythonhosted.org/packages/e4/e6/f9cf79926273920d6091d706babc27989c3c1633de6ba6072157348ea3a8/xmljson-0.2.0-py2.py3-none-any.whl
Installing collected packages: lxml, xmljson
Successfully installed lxml-4.5.0 xmljson-0.2.0
$ cat xml2json.py
python3
1import sys 2from lxml import etree 3import xmljson 4import json 5 6tree = etree.parse(sys.stdin) 7 8dic = xmljson.yahoo.data(tree.getroot()) 9 10json.dump(dic, sys.stdout, indent=2) 11
$ cat data.txt | python data2xml.py | python xml2json.py > data.json
$ cat data.json
json
1{ 2 "data": { 3 "key1": [ 4 "value1", 5 "value3" 6 ], 7 "key2": "value2" 8 } 9}
上記では、data2xmlとdata2xml、ともにPythonで書きましたが、プログラミング言語として何を使うかは、この回答の本題ではなく、「中間形式としてXMLにしてみてはいかがでしょう?」というご提案が主旨になります。
また、上記のコードでは、XMLからJSONにするのに、xmljsonという既存モジュールを使いましたが、XMLをパースしてXPathで欲しい情報だけを拾って別の形式のJSONにすることもできます。このように、独自形式の元データをXMLに変換すれば、その後はXMLという汎用的な形式を処理するという、解法のヒントが多く得られる問題に置き換えることができるので、採り得る選択肢が広がるのではと考えた次第です。
以上、参考になれば幸いです。
投稿2020/04/07 21:24
総合スコア9058
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
文字列処理するしかないので、こういうパターンを考えてみました。
javascript
1var code = `{ 2'key1': value1, 3'key2': value2, 4'key1': value3 5}` 6 7var parse = str => { 8 let oj = {}; 9 let set = (k,v) => { 10 if( ! oj.hasOwnProperty(k) ) oj[k] = v; 11 else if( !Array.isArray(oj[k]) ) { 12 oj[k] = [oj[k]]; 13 } 14 if( Array.isArray(oj[k]) ) oj[k].push(v); 15 } 16 17 str.split(/\x2c?\n/).forEach( token => { 18 console.log(" token ", token ); 19 let m; 20 if( m = token.match(/\x27([\w\d]+)\x27\x3a\s*([\w\d]+)/) ) { 21 console.log("pair-match ", m ); 22 set(m[1],m[2]); 23 } 24 }) 25 26 return oj; 27} 28 29var json = parse( code ); 30 31console.log( JSON.stringify(json,null,2) ); 32/* 33{ 34 "key1": [ 35 "value1", 36 "value3" 37 ], 38 "key2": "value2" 39} 40 */
投稿2020/04/07 11:10
総合スコア5434
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。