Nous avons la chaîne suivante qui est un JSON valide écrit dans un fichier sur HDFS.
{
"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"
}
}
}
MODIFIER
Nous configurons un agent flume qui lit les données de ce fichier et les transmettons à Solr sink mais malheureusement cette exception dans le titre est throw.
et voici la trace de la pile
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
Nous avons la chaîne suivante qui est un JSON valide ...
Clairement, l'analyseur JSON n'est pas d'accord!
Cependant, l'exception indique que l'erreur se trouve à "ligne 1: colonne 9" et qu'il n'y a pas de jeton "http" près du début du JSON. Je soupçonne donc que l'analyseur essaie d'analyser quelque chose de différent de cette chaîne lorsque l'erreur se produit.
Vous devez trouver ce qu'est JSON en fait en cours d'analyse. Exécutez l'application dans un débogueur, définissez un point d'arrêt sur le constructeur approprié pour JsonParseException
... puis découvrez ce qui se trouve dans le ByteArrayInputStream
qu'il tente d'analyser.
J'ai fait face à cette exception pendant longtemps et je n'ai pas pu identifier le problème. L'exception indique la ligne 1 de la colonne 9. L'erreur que j'ai faite est d'avoir la première ligne du fichier traité par flume.
Apache flume traite le contenu du fichier par patchs. Ainsi, lorsque flume lève cette exception et dit la ligne 1, cela signifie la première ligne du patch actuel.
Si votre agent de canal est configuré pour utiliser la taille de lot = 100 et (par exemple) le fichier contient 400 lignes, cela signifie que l'exception est levée dans l'une des lignes suivantes 1, 101, 201,301.
Comment découvrir la ligne à l'origine du problème?
Vous avez trois façons de procéder.
1- tirez le code source et exécutez l'agent en mode débogage. Si vous êtes un développeur moyen comme moi et que vous ne savez pas comment procéder, vérifiez les deux autres options.
2- Essayez de diviser le fichier en fonction de la taille du lot et réexécutez l'agent flume. Si vous divisez le fichier en 4 fichiers et que le json non valide existe entre les lignes 301 et 400, l'agent flume traitera les 3 premiers fichiers et s'arrêtera au quatrième fichier. Prenez le quatrième fichier et divisez-le à nouveau en fichiers plus petits. continuez le processus jusqu'à ce que vous atteigniez un fichier avec une seule ligne et que flume échoue pendant le traitement.
3- Réduisez la taille du lot de l'agent de canal à un seul et comparez le nombre d'événements traités dans la sortie de l'évier que vous utilisez. Par exemple, dans mon cas, j'utilise un évier Solr. Le fichier contient 400 lignes. L'agent de canal est configuré avec une taille de lot = 100. Lorsque j'exécute l'agent flume, il échoue à un moment donné et jette cette exception. À ce stade, vérifiez le nombre de documents ingérés dans Solr. Si le json non valide existe à la ligne 346, le nombre de documents indexés dans Solr sera 345, donc la ligne suivante est la ligne à l'origine du problème.
Dans mon cas, j'ai suivi la troisième option et, heureusement, j'ai identifié la ligne à l'origine du problème.
C'est une longue réponse, mais cela ne résout pas l'exception. Comment surmonter cette exception?
Je ne sais pas pourquoi la bibliothèque Jackson se plaint lors de l'analyse d'une chaîne json contenant des caractères d'échappement \n \r \t
. Je pense (mais je ne suis pas sûr) que l'analyseur Jackson échappe par défaut à ces caractères, ce qui casse la chaîne json à diviser en deux lignes (dans le cas de \n
), puis il traite chaque ligne comme une chaîne json distincte.
Dans mon cas, nous avons utilisé un intercepteur personnalisé pour supprimer ces caractères avant d'être traités par l'agent flume. C'est ainsi que nous avons résolu ce problème.
Cela peut être évident, mais assurez-vous que vous envoyez à l'objet URL de l'analyseur pas une chaîne contenant l'adresse www. Cela pas fonctionnera:
ObjectMapper mapper = new ObjectMapper();
String www = "www.sample.pl";
Weather weather = mapper.readValue(www, Weather.class);
Mais cela:
ObjectMapper mapper = new ObjectMapper();
URL www = new URL("http://www.Oracle.com/");
Weather weather = mapper.readValue(www, Weather.class);