HDFS上のファイルに書き込まれる有効なJSONである次の文字列があります。
{
"id":"tag:search.Twitter.com,2005:564407444843950080",
"objectType":"activity",
"actor":{
"objectType":"person",
"id":"id:Twitter.com:2302910022",
"link":"http%3A%2F%2Fwww.Twitter.com%2Fme7me4610012",
"displayName":"",
"postedTime":"2014-01-21T11:06:06.000Z",
"image":"https%3A%2F%2Fpbs.twimg.com%2Fprofile_images%2F563125491159162881%2FfypkHK3M_normal.jpeg",
"summary":"ضًـأّيِّعٌهّ أّروٌأّحًنِأّ تٌـشُـتٌـهّـيِّ مًنِ يِّفُـهّـمًهّـأّ فُـقُط حسابي بالإنستقرام lloooo_20",
"links":[
{
"href":null,
"rel":"me"
}
],
"friendsCount":10503,
"followersCount":10325,
"listedCount":12,
"statusesCount":84957,
"twitterTimeZone":null,
"verified":false,
"utcOffset":null,
"preferredUsername":"me7me4610012",
"languages":[
"ar"
],
"favoritesCount":17
},
"verb":"share",
"postedTime":"2015-02-08T12:56:35.000Z",
"generator":{
"displayName":"Twitter for Android",
"link":"http%3A%2F%2Ftwitter.com%2Fdownload%2Fandroid"
},
"provider":{
"objectType":"service",
"displayName":"Twitter",
"link":"http%3A%2F%2Fwww.Twitter.com"
},
"link":"http%3A%2F%2Ftwitter.com%2Fme7me4610012%2Fstatuses%2F564407444843950080",
"body":"RT @sckud1: فيديو: إمام يرفض بغضب الصلاة على أحد قتلى حزب الله في سوريا بسبب إطلاق النار: ماعاد http%3A%2F%2Ft.co%2FC55SaQKmUV http%3A%2F%2Ft.co%2Ft5TjIln…",
"object":{
"id":"tag:search.Twitter.com,2005:564407126526013440",
"objectType":"activity",
"actor":{
"objectType":"person",
"id":"id:Twitter.com:462268717",
"link":"http%3A%2F%2Fwww.Twitter.com/sckud1",
"displayName":"صفق الهوى",
"postedTime":"2012-01-12T19:24:17.000Z",
"image":"https%3A%2F%2Fpbs.twimg.com%2Fprofile_images%2F508424482885615616%2FmPBGZBPx_normal.jpeg",
"summary":"اعلانك في سوق الخليج يحقق لك الوصول الى اكثر من مليون متابع خليجي http%3A%2F%2Fmarketgulf.com",
"links":[
{
"href":"http%3A%2F%2Fmarketgulf.com",
"rel":"me"
}
],
"friendsCount":435237,
"followersCount":464951,
"listedCount":708,
"statusesCount":1071685,
"twitterTimeZone":"Riyadh",
"verified":false,
"utcOffset":"10800",
"preferredUsername":"sckud1",
"languages":[
"ar"
],
"location":{
"objectType":"place",
"displayName":"Made in K S A"
},
"favoritesCount":77
},
"verb":"post",
"postedTime":"2015-02-08T12:55:19.000Z",
"generator":{
"displayName":"Tweet Old Post",
"link":"http%3A%2F%2Fwww.ajaymatharu.com%2F"
},
"provider":{
"objectType":"service",
"displayName":"Twitter",
"link":"http%3A%2F%2Fwww.Twitter.com"
},
"link":"http%3A%2F%2Ftwitter.com%2Fsckud1%2Fstatuses%2F564407126526013440",
"body":"فيديو: إمام يرفض بغضب الصلاة على أحد قتلى حزب الله في سوريا بسبب إطلاق النار: ماعاد http%3A%2F%2Ft.co%2FC55SaQKmUV http%3A%2F%2Ft.co%2Ft5TjIlnZgN",
"object":{
"objectType":"note",
"id":"object:search.Twitter.com,2005:564407126526013440",
"summary":"فيديو: إمام يرفض بغضب الصلاة على أحد قتلى حزب الله في سوريا بسبب إطلاق النار: ماعاد http%3A%2F%2Ft.co%2FC55SaQKmUV http%3A%2F%2Ft.co%2Ft5TjIlnZgN",
"link":"http%3A%2F%2Ftwitter.com%2Fsckud1%2Fstatuses%2F564407126526013440",
"postedTime":"2015-02-08T12:55:19.000Z"
},
"favoritesCount":0,
"Twitter_entities":{
"hashtags":[
],
"trends":[
],
"urls":[
{
"url":"http%3A%2F%2Ft.co%2FC55SaQKmUV",
"expanded_url":"http%3A%2F%2Fwww.hasterya.com%2Farchives%2F34688utm_source%3DReviveOldPost%26utm_medium%3Dsocial%26utm_campaign%3DReviveOldPost",
"display_url":"hasterya.com/archives/34688…",
"indices":[
85,
107
]
}
],
"user_mentions":[
],
"symbols":[
],
"media":[
{
"id":564407126341468160,
"id_str":"564407126341468160",
"indices":[
108,
130
],
"media_url":"http%3A%2F%2Fpbs.twimg.com%2Fmedia%2FB9UtSoJIQAA07-r.jpg",
"media_url_https":"https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FB9UtSoJIQAA07-r.jpg",
"url":"http%3A%2F%2Ft.co%2Ft5TjIlnZgN",
"display_url":"pic.Twitter.com/t5TjIlnZgN",
"expanded_url":"http%3A%2F%2Ftwitter.com%2Fsckud1%2Fstatus%2F564407126526013440%2Fphoto%2F1",
"type":"photo",
"sizes":{
"large":{
"w":320,
"h":180,
"resize":"fit"
},
"thumb":{
"w":150,
"h":150,
"resize":"crop"
},
"small":{
"w":320,
"h":180,
"resize":"fit"
},
"medium":{
"w":320,
"h":180,
"resize":"fit"
}
}
}
]
},
"Twitter_extended_entities":{
"media":[
{
"id":564407126341468160,
"id_str":"564407126341468160",
"indices":[
108,
130
],
"media_url":"http%3A%2F%2Fpbs.twimg.com%2Fmedia%2FB9UtSoJIQAA07-r.jpg",
"media_url_https":"https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FB9UtSoJIQAA07-r.jpg",
"url":"http%3A%2F%2Ft.co%2Ft5TjIlnZgN",
"display_url":"pic.Twitter.com/t5TjIlnZgN",
"expanded_url":"http%3A%2F%2Ftwitter.com%2Fsckud1%2Fstatus%2F564407126526013440%2Fphoto%2F1",
"type":"photo",
"sizes":{
"large":{
"w":320,
"h":180,
"resize":"fit"
},
"thumb":{
"w":150,
"h":150,
"resize":"crop"
},
"small":{
"w":320,
"h":180,
"resize":"fit"
},
"medium":{
"w":320,
"h":180,
"resize":"fit"
}
}
}
]
},
"Twitter_filter_level":"low",
"Twitter_lang":"ar"
},
"favoritesCount":0,
"Twitter_entities":{
"hashtags":[
],
"trends":[
],
"urls":[
{
"url":"http%3A%2F%2Ft.co%2FC55SaQKmUV",
"expanded_url":"http%3A%2F%2Fwww.hasterya.com%2Farchives%2F34688utm_source%3DReviveOldPost%26utm_medium%3Dsocial%26utm_campaign%3DReviveOldPost",
"display_url":"hasterya.com/archives/34688…",
"indices":[
97,
119
]
}
],
"user_mentions":[
{
"screen_name":"sckud1",
"name":"صفق الهوى",
"id":462268717,
"id_str":"462268717",
"indices":[
3,
10
]
}
],
"symbols":[
],
"media":[
{
"id":564407126341468160,
"id_str":"564407126341468160",
"indices":[
139,
140
],
"media_url":"http%3A%2F%2Fpbs.twimg.com%2Fmedia%2FB9UtSoJIQAA07-r.jpg",
"media_url_https":"https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FB9UtSoJIQAA07-r.jpg",
"url":"http%3A%2F%2Ft.co%2Ft5TjIlnZgN",
"display_url":"pic.Twitter.com/t5TjIlnZgN",
"expanded_url":"http%3A%2F%2Ftwitter.com%2Fsckud1%2Fstatus%2F564407126526013440%2Fphoto%2F1",
"type":"photo",
"sizes":{
"large":{
"w":320,
"h":180,
"resize":"fit"
},
"thumb":{
"w":150,
"h":150,
"resize":"crop"
},
"small":{
"w":320,
"h":180,
"resize":"fit"
},
"medium":{
"w":320,
"h":180,
"resize":"fit"
}
},
"source_status_id":564407126526013440,
"source_status_id_str":"564407126526013440"
}
]
},
"Twitter_extended_entities":{
"media":[
{
"id":564407126341468160,
"id_str":"564407126341468160",
"indices":[
139,
140
],
"media_url":"http%3A%2F%2Fpbs.twimg.com%2Fmedia%2FB9UtSoJIQAA07-r.jpg",
"media_url_https":"https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FB9UtSoJIQAA07-r.jpg",
"url":"http%3A%2F%2Ft.co%2Ft5TjIlnZgN",
"display_url":"pic.Twitter.com/t5TjIlnZgN",
"expanded_url":"http%3A%2F%2Ftwitter.com%2Fsckud1%2Fstatus%2F564407126526013440%2Fphoto%2F1",
"type":"photo",
"sizes":{
"large":{
"w":320,
"h":180,
"resize":"fit"
},
"thumb":{
"w":150,
"h":150,
"resize":"crop"
},
"small":{
"w":320,
"h":180,
"resize":"fit"
},
"medium":{
"w":320,
"h":180,
"resize":"fit"
}
},
"source_status_id":564407126526013440,
"source_status_id_str":"564407126526013440"
}
]
},
"Twitter_filter_level":"low",
"Twitter_lang":"ar",
"retweetCount":1,
"gnip":{
"matching_rules":[
{
"tag":"ISIS66"
}
],
"urls":[
{
"url":"http%3A%2F%2Ft.co%2Ft5TjIlnZgN",
"expanded_url":"http%3A%2F%2Ftwitter.com%2Fsckud1%2Fstatus%2F564407126526013440%2Fphoto%2F1",
"expanded_status":200
},
{
"url":"http%3A%2F%2Ft.co%2FC55SaQKmUV",
"expanded_url":"http%3A%2F%2Fwww.hasterya.com%2Farchives%2F34688utm_source%3DReviveOldPost%26utm_medium%3Dsocial%26utm_campaign%3DReviveOldPost",
"expanded_status":200
}
],
"klout_score":50,
"language":{
"value":"ar"
}
}
}
[〜#〜] edit [〜#〜]
そのファイルからデータを読み取り、それをSolrシンクに渡すflumeエージェントを構成しますが、残念ながらタイトルのこの例外はスローされます。
そして、これはスタックトレースです
org.kitesdk.morphline.api.MorphlineRuntimeException: com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'http': was expecting ('true', 'false' or 'null')
at [Source: Java.io.ByteArrayInputStream@20d7aa52; line: 1, column: 9]
at org.kitesdk.morphline.stdio.AbstractParser.doProcess(AbstractParser.Java:98)
at org.kitesdk.morphline.base.AbstractCommand.process(AbstractCommand.Java:156)
at org.kitesdk.morphline.stdlib.TryRulesBuilder$TryRules.doProcess(TryRulesBuilder.Java:120)
at org.kitesdk.morphline.base.AbstractCommand.process(AbstractCommand.Java:156)
at org.kitesdk.morphline.base.AbstractCommand.doProcess(AbstractCommand.Java:181)
at org.kitesdk.morphline.base.AbstractCommand.process(AbstractCommand.Java:156)
at org.Apache.flume.sink.solr.morphline.MorphlineHandlerImpl.process(MorphlineHandlerImpl.Java:128)
at org.Apache.flume.sink.solr.morphline.MorphlineSink.process(MorphlineSink.Java:141)
at org.Apache.flume.sink.DefaultSinkProcessor.process(DefaultSinkProcessor.Java:68)
at org.Apache.flume.SinkRunner$PollingRunner.run(SinkRunner.Java:147)
at Java.lang.Thread.run(Thread.Java:744)
Caused by: com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'http': was expecting ('true', 'false' or 'null')
at [Source: Java.io.ByteArrayInputStream@20d7aa52; line: 1, column: 9]
at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.Java:1524)
at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.Java:557)
at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._reportInvalidToken(UTF8StreamJsonParser.Java:3095)
at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._handleUnexpectedValue(UTF8StreamJsonParser.Java:2340)
at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._nextTokenNotInObject(UTF8StreamJsonParser.Java:818)
at com.fasterxml.jackson.core.json.UTF8StreamJsonParser.nextToken(UTF8StreamJsonParser.Java:698)
at com.fasterxml.jackson.databind.MappingIterator.hasNextValue(MappingIterator.Java:159)
at org.kitesdk.morphline.json.ReadJsonBuilder$ReadJson.doProcess(ReadJsonBuilder.Java:109)
at org.kitesdk.morphline.stdio.AbstractParser.doProcess(AbstractParser.Java:96)
... 10 more
有効なJSONである次の文字列があります...
明らかに、JSONパーサーは一致しません!
ただし、例外は「行1:列9」にエラーがあり、JSONの先頭付近に「http」トークンがないことを示しています。したがって、エラーが発生したときに、パーサーがこの文字列とは異なる何かを解析しようとしているのではないかと考えています。
JSONが何であるかを見つける必要があります実際解析されています。デバッガー内でアプリケーションを実行し、JsonParseException
の関連するコンストラクターにブレークポイントを設定してから、ByteArrayInputStream
内で解析しようとしているものを見つけます。
私は長い間この例外に直面し、問題を特定することができませんでした。例外は1行9列です。私がした間違いは、flumeが処理しているファイルの最初の行を取得することです。
Apache flumeは、パッチのファイルのコンテンツを処理します。したがって、flumeがこの例外をスローして1行目を言うと、現在のパッチの最初の行を意味します。
Flumeエージェントがバッチサイズ= 100を使用するように構成されており、(たとえば)ファイルに400行が含まれている場合、これは次の行1、101、201、301のいずれかで例外がスローされることを意味します。
問題の原因となっている行を見つける方法
それには3つの方法があります。
1-ソースコードをプルし、デバッグモードでエージェントを実行します。あなたが私のような平均的な開発者であり、これを作成する方法がわからない場合は、他の2つのオプションを確認してください。
2-バッチサイズに基づいてファイルを分割し、flumeエージェントを再度実行します。ファイルを4つのファイルに分割し、301行目と400行目の間に無効なjsonが存在する場合、flumeエージェントは最初の3つのファイルを処理し、4番目のファイルで停止します。 4番目のファイルを取得し、さらに小さなファイルに分割します。 1行だけのファイルに到達し、処理中にflumeが失敗するまでプロセスを続けます。
3- flumeエージェントのバッチサイズを1つに減らし、使用しているシンクの出力で処理されたイベントの数を比較します。たとえば、私の場合、Solrシンクを使用しています。ファイルには400行が含まれています。 flumeエージェントは、バッチサイズ= 100で構成されます。 flumeエージェントを実行すると、ある時点で失敗し、その例外をスローします。この時点で、Solrで取り込んだドキュメントの数を確認します。 346行目に無効なjsonが存在する場合、Solrにインデックス付けされるドキュメントの数は345になるため、次の行は問題の原因となる行です。
私の場合、3番目のオプションに従って、幸いなことに、問題の原因となっている行を特定しました。
これは長い答えですが、実際には例外を解決しません。この例外をどのように克服しますか?
JSON文字列の解析中にエスケープ文字\n \r \t
が含まれているのに、Jacksonライブラリが文句を言う理由がわかりません。 Jacksonパーサーはデフォルトでこれらの文字をエスケープしていると思います(\n
の場合)、json文字列は2行に分割され、各行は個別のjson文字列として扱われます。
私の場合、カスタマイズされたインターセプターを使用して、flumeエージェントによって処理される前にこれらの文字を削除しました。これがこの問題を解決した方法です。
明らかかもしれませんが、wwwアドレスを含む文字列ではなく、パーサーURLオブジェクトに送信していることを確認してください。これはnot動作します:
ObjectMapper mapper = new ObjectMapper();
String www = "www.sample.pl";
Weather weather = mapper.readValue(www, Weather.class);
しかし、これは:
ObjectMapper mapper = new ObjectMapper();
URL www = new URL("http://www.Oracle.com/");
Weather weather = mapper.readValue(www, Weather.class);