Code is given first chance exception in foreach loop C# - exception

This is my code that is generating first chance exception but i think foreach loop first check the null reference before iterating then why a System. NullReferenceException ??
HtmlNodeCollection nodes = crawledPage.HtmlDocument.DocumentNode.SelectNodes("//table");
foreach (HtmlNode node in nodes)
{
if (Regex.IsMatch(node.GetAttributeValue("class", ""), #"infobox(.)*"))
{
Program.con.Insert(crawledPage.ParentUri.AbsoluteUri, crawledPage.Uri.AbsoluteUri, node.OuterHtml);
}
}
if anyone clairify i will appreciate

Related

PHP7, JSON and Zend (decoding failed: syntax error)

I recently upgraded to PHP 7.0.4 and nginx 1.8.1, my application uses the Zend Framework (Magento 1.9.2.1). Since that upgrade, our customers sometimes get an "Decoding failed: Syntax error" when submitting an orderm which is thrown in
public static function decode($encodedValue, $objectDecodeType = Zend_Json::TYPE_ARRAY)
{
$encodedValue = (string) $encodedValue;
if (function_exists('json_decode') && self::$useBuiltinEncoderDecoder !== true) {
$decode = json_decode($encodedValue, $objectDecodeType);
// php < 5.3
if (!function_exists('json_last_error')) {
if (strtolower($encodedValue) === 'null') {
return null;
} elseif ($decode === null) {
#require_once 'Zend/Json/Exception.php';
throw new Zend_Json_Exception('Decoding failed');
}
// php >= 5.3
} elseif (($jsonLastErr = json_last_error()) != JSON_ERROR_NONE) {
#require_once 'Zend/Json/Exception.php';
switch ($jsonLastErr) {
case JSON_ERROR_DEPTH:
throw new Zend_Json_Exception('Decoding failed: Maximum stack depth exceeded');
case JSON_ERROR_CTRL_CHAR:
throw new Zend_Json_Exception('Decoding failed: Unexpected control character found');
case JSON_ERROR_SYNTAX:
throw new Zend_Json_Exception('Decoding failed: Syntax error');
default:
throw new Zend_Json_Exception('Decoding failed');
}
}
return $decode;
}
I read about a bug that PHP7 and JSON decode behaves differently when encoding an empty string. Does anyone know if this bug is related to PHP7 or to my application/server?
Thanks
This is an absolutely normal behaviour of json_decode.
It will throw this exception if the given string is not a valid JSON String.
As you already mentioned, an empty string is also not a valid JSON String.
json_decode('Hello') // invalid
json_decode("Hello") //invalid
But:
json_decode("'Hello'") // valid JSON string
Empty strings will raise an exception since PHP7!
"Calling json_decode with 1st argument equal to empty PHP string or value that after casting to string is empty string (NULL, FALSE) results in JSON syntax error."
So... to answer your question: In my opinion, your application has the problem you need to solve, if downgrading your PHP version is not an option.
The Magenta function needs to check for a valid representation of a JSON string BEFORE passing it to the json_decode function.
Try to set the variable to {} if it is not a string (is_string) or if it is empty.
If this is not the problem, it might be possible that your string is not encoded as it should be. Many times encoding of the strings passed to json_decode will result into that exception also.
One possible (dirty) fix is to set the build in decoder of Zend to true, while this may be much slower this does work on PHP7 where the default package errors out.
in class Zend_Json, set $useBuiltinEncoderDecoder to true;
public static function decode($encodedValue, $objectDecodeType = Zend_Json::TYPE_ARRAY)
{
$encodedValue = (string) $encodedValue;
if (function_exists('json_decode') && self::$useBuiltinEncoderDecoder !== true) {
This way the return Zend_Json_Decoder::decode($encodedValue, $objectDecodeType); will be used which seems to be working just fine.
Dirty hack:
In my case it was a problem in Magento 2.2 with PHP7 where an empty object would throw an error. It would prevent the product indexer from completing.
So I added an empty array return for this case (in file vendor/magento/zendframework1/library/Zend/Json.php):
public static function decode($encodedValue, $objectDecodeType = Zend_Json::TYPE_ARRAY)
{
$encodedValue = (string) $encodedValue;
if($encodedValue == "a:0:{}") { return []; } //<- added: return an empty array
if (function_exists('json_decode') && self::$useBuiltinEncoderDecoder !== true) {
....
I have the same problem. I have a temporary fix as follows, waiting for a better solution
//return Zend_Json::decode($data->params);
return json_decode($data->params);
This was fixed in zend-mvc 3.1.1

Detect an empty [{}] json object in managed code

Our application uses json files for configuration.
If the file has configuration data we parse it and all goes well.
If the file has bad data [{ asdf 34453 %^$% dfgdsf }] we handle just fine
If the config file is missing then we handle that.
The scenario I'm trying to figure out is if it is an empty object such as [{}] I'm looking for a reliable way by checking the first Xnode, last Xnode, Xattribute..something because HasElements will return true for an empty object.
Please don't suggest using 3rd part libraries etc. Not happening as decided by others.
The code I am using:
private static bool TryParseJson(MemoryStream msJson)
{
bool IsValid = false;
XElement root;
XmlReader xReader = JsonReaderWriterFactory.CreateJsonReader(msJson, new XmlDictionaryReaderQuotas());
//an empty json file ( [] ) will parse but have no elements hence the elements check.
//a file full of giberish...incorrect json format will fail to parse and throw exception hence the try catch
try
{
root = XElement.Load(xReader);
}
catch
{
return IsValid;
}
//an empty file ( [{}] will return positive for HasElements so we also get ?????
XNode ???? = root.FirstNode;
if (root.HasElements && !???)
{
IsValid = true;
return IsValid;
}
return IsValid;
}
I think I have found a way to handle an empty object. My testing with valid json and empty json shows that an empty object [{}] will still return a single element but there will be NO nodes in that element so I went with this:
//an empty file ( [{}] will return positive for HasElements so we also get
bool IsEmptyObject = (root.Elements().Nodes().Count() > 0) ? true : false;
I'd still be interested in hearing the contributions of others.
Thanks

PowerShell changes return object's type

I am using PowerShell v3 and the Windows PowerShell ISE. I have the following function that works fine:
function Get-XmlNode([xml]$XmlDocument, [string]$NodePath, [string]$NamespaceURI = "", [string]$NodeSeparatorCharacter = '.')
{
# If a Namespace URI was not given, use the Xml document's default namespace.
if ([string]::IsNullOrEmpty($NamespaceURI)) { $NamespaceURI = $XmlDocument.DocumentElement.NamespaceURI }
# In order for SelectSingleNode() to actually work, we need to use the fully qualified node path along with an Xml Namespace Manager, so set them up.
[System.Xml.XmlNamespaceManager]$xmlNsManager = New-Object System.Xml.XmlNamespaceManager($XmlDocument.NameTable)
$xmlNsManager.AddNamespace("ns", $NamespaceURI)
[string]$fullyQualifiedNodePath = Get-FullyQualifiedXmlNodePath -NodePath $NodePath -NodeSeparatorCharacter $NodeSeparatorCharacter
# Try and get the node, then return it. Returns $null if the node was not found.
$node = $XmlDocument.SelectSingleNode($fullyQualifiedNodePath, $xmlNsManager)
return $node
}
Now, I will be creating a few similar functions, so I want to break the first 3 lines out into a new function so that I don't have to copy-paste them everywhere, so I have done this:
function Get-XmlNamespaceManager([xml]$XmlDocument, [string]$NamespaceURI = "")
{
# If a Namespace URI was not given, use the Xml document's default namespace.
if ([string]::IsNullOrEmpty($NamespaceURI)) { $NamespaceURI = $XmlDocument.DocumentElement.NamespaceURI }
# In order for SelectSingleNode() to actually work, we need to use the fully qualified node path along with an Xml Namespace Manager, so set them up.
[System.Xml.XmlNamespaceManager]$xmlNsManager = New-Object System.Xml.XmlNamespaceManager($XmlDocument.NameTable)
$xmlNsManager.AddNamespace("ns", $NamespaceURI)
return $xmlNsManager
}
function Get-XmlNode([xml]$XmlDocument, [string]$NodePath, [string]$NamespaceURI = "", [string]$NodeSeparatorCharacter = '.')
{
[System.Xml.XmlNamespaceManager]$xmlNsManager = Get-XmlNamespaceManager -XmlDocument $XmlDocument -NamespaceURI $NamespaceURI
[string]$fullyQualifiedNodePath = Get-FullyQualifiedXmlNodePath -NodePath $NodePath -NodeSeparatorCharacter $NodeSeparatorCharacter
# Try and get the node, then return it. Returns $null if the node was not found.
$node = $XmlDocument.SelectSingleNode($fullyQualifiedNodePath, $xmlNsManager)
return $node
}
The problem is that when "return $xmlNsManager" executes the following error is thrown:
Cannot convert the "System.Object[]" value of type "System.Object[]" to type "System.Xml.XmlNamespaceManager".
So even though I have explicitly cast my $xmlNsManager variables to be of type System.Xml.XmlNamespaceManager, when it gets returned from the Get-XmlNamespaceManager function PowerShell is converting it to an Object array.
If I don't explicitly cast the value returned from the Get-XmlNamespaceManager function to System.Xml.XmlNamespaceManager, then the following error is thrown from the .SelectSingleNode() function because the wrong data type is being passed into the function's 2nd parameter.
Cannot find an overload for "SelectSingleNode" and the argument count: "2".
So for some reason PowerShell is not maintaining the data type of the return variable. I would really like to get this working from a function so that I don't have to copy-paste those 3 lines all over the place. Any suggestions are appreciated. Thanks.
What's happening is PowerShell is converting your namespace manager object to a string array.
I think it has to do with PowerShell's nature of "unrolling" collections when sending objects down the pipeline. I think PowerShell will do this for any type implementing IEnumerable (has a GetEnumerator method).
As a work around you can use the comma trick to prevent this behavior and send the object as a whole collection.
function Get-XmlNamespaceManager([xml]$XmlDocument, [string]$NamespaceURI = "")
{
...
$xmlNsManager.AddNamespace("ns", $NamespaceURI)
return ,$xmlNsManager
}
More specifically, what is happening here is that your coding habit of strongly typing $fullyQualifiedModePath is trying to turn the result of the Get (which is a list of objects) into a string.
[string]$foo
will constrain the variable $foo to only be a string, no matter what came back. In this case, your type constraint is what is subtly screwing up the return and making it Object[]
Also, looking at your code, I would personally recommend you use Select-Xml (built into V2 and later), rather than do a lot of hand-coded XML unrolling. You can do namespace queries in Select-Xml with -Namespace #{x="..."}.

Flex3 issue to get the array format using json object

{"object":[{"cyclename":"PE cycle","avgRunTime":"05:30","actualStartTime":"08/27/2011 02:40:08","actualEndTime":"08/27/2011 05:26:38","startTime":"02:40","status":"G"}]}
this is my file and i want to parse it to array and get the status displayed but i am getting data like [object object][object Object],[object Object],[object Object] etc...
how do i parse it to a dataprovider and code i have written is
private function cycle_resultHandler(event:ResultEvent):void
{
var myData:Object = JSON.decode(event.result as String);
for(var i:String in myData['object'])
{
dProvider.addItem(myData['object'][i]);
}
}
Your looping seems to be a bit off. First off you may want to reconsider your usage of a "for ...in" loop vs. a "for each" loop. This article: for...in vs. for each explains the differences quite plainly.
You may also want to give this article a read for more information on object introspection (a technique for determining the properties of a class at runtime -- what you are trying to do...).
In any case, the issue here is what you are looping over. If the goal here is to loop over the property values of "object" and add them to an array or arraycollection, you're almost there--
utilizing a "for each" loop you might do this instead:
private function cycle_resultHandler(event:ResultEvent):void {
var myData:Object = JSON.decode(event.result as String);
//Here we are iterating over the values in the "object" object as opposed to it's keys.
for each(var str:String in myData['object']) {
dProvider.addItem(str);
}
}
Hope this helps :)

Data type conversion issues in Powershell

I'm writing a Powershell script that will extract a set of data files from a ZIP file and will then attach them to a server. I've written a function that takes care of the unzip and since I need to grab all of the files so that I know what I'm attaching I return that from the function:
function Unzip-Files
{
param([string]$zip_path, [string]$zip_filename, [string]$target_path, [string]$filename_pattern)
# Append a \ if the path doesn't already end with one
if (!$zip_path.EndsWith("\")) {$zip_path = $zip_path + "\"}
if (!$target_path.EndsWith("\")) {$target_path = $target_path + "\"}
# We'll need a string collection to return the files that were extracted
$extracted_file_names = New-Object System.Collections.Specialized.StringCollection
# We'll need a Shell Application for some file movement
$shell_application = New-Object -com shell.Application
# Get a handle for the target folder
$target_folder = $shell_application.NameSpace($target_path)
$zip_full_path = $zip_path + $zip_filename
if (Test-Path($zip_full_path))
{
$target_folder = $shell_application.NameSpace($target_path)
$zip_folder = $shell_application.NameSpace($zip_full_path)
foreach ($zipped_file in $zip_folder.Items() | Where {$_.Name -like $filename_pattern})
{
$extracted_file_names.Add($zipped_file.Name) | Out-Null
$target_folder.CopyHere($zipped_file, 16)
}
}
$extracted_file_names
}
I then call another function to actually attach the database (I've removed some code that checks for existence of the database, but that shouldn't affect things here):
function Attach-Database
{
param([object]$server, [string]$database_name, [object]$datafile_names)
$database = $server.Databases[$database_name]
$server.AttachDatabase($database_name, $datafile_names)
$database = $server.Databases[$database_name]
Return $database
}
I keep getting an error though, "Cannot convert argument "1", with value: "System.Object[]", for "AttachDatabase" to type "System.Collections.Specialized.StringCollection"".
I've tried declaring the data types explicitly at various points, but that just changes the location where I get the error (or one similar to it). I've also changed the parameter declaration to use the string collection instead of object with no luck.
I'm starting with a string collection and ultimately want to consume a string collection. I just don't seem to be able to get Powershell to stop trying to convert it to a generic Object at some point.
Any suggestions?
Thanks!
It looks like you should return the names using the comma operator:
...
, $extracted_file_names
}
to avoid "unrolling" the collection to its items and to preserve the original collection object.
There were several questions like this, here is just a couple:
Strange behavior in PowerShell function returning DataSet/DataTable
Loading a serialized DataTable in PowerShell - Gives back array of DataRows not a DataTable
UPDATE:
This similar code works:
Add-Type #'
using System;
using System.Collections.Specialized;
public static class TestClass
{
public static string TestMethod(StringCollection data)
{
string result = "";
foreach (string s in data)
result += s;
return result;
}
}
'#
function Unzip-Files
{
$extracted_file_names = New-Object System.Collections.Specialized.StringCollection
foreach ($zipped_file in 'xxx', 'yyy', 'zzz')
{
$extracted_file_names.Add($zipped_file) | Out-Null
}
, $extracted_file_names
}
function Attach-Database
{
param([object]$datafile_names)
# write the result
Write-Host ([TestClass]::TestMethod($datafile_names))
}
# get the collection
$names = Unzip-Files
# write its type
Write-Host $names.GetType()
# pass it in the function
Attach-Database $names
As expected, its output is:
System.Collections.Specialized.StringCollection
xxxyyyzzz
If I remove the suggested comma, then we get:
System.Object[]
Cannot convert argument "0", with value: "System.Object[]",
for "TestMethod" to type "System.Collections.Specialized.StringCollection"...
The symptoms look the same, so the solution presumably should work, too, if there are no other unwanted conversions/unrolling in the omitted code between Unzip-Files and Attach-Database calls.