Skip to content

Conversation

@chunqingchen
Copy link
Contributor

This is to resolve #4996
Newtonsoft.Json.Linq.Jproperty is not properly handled.

Adding handling for Newtonsoft.Json.Linq.Jproperty

Repro:
$EgJObject = New-Object -TypeName Newtonsoft.Json.Linq.JObject
$EgJObject.Add("TestValue1", "123456")
$EgJObject.Add("TestValue2", "78910")
$EgJObject.Add("TestValue3", "99999")
$dict = @{}
$dict.Add('JObject', $EgJObject)
$dict.Add('StrObject', 'This is a string Object')
$properties = @{'DictObject' = $dict; 'RandomString' = 'A quick brown fox jumped over the lazy dog'}
$object = New-Object -TypeName psobject -Property $properties
$object | ConvertTo-Json

Before fix:

{
"RandomString": "A quick brown fox jumped over the lazy dog",
"DictObject": {
"JObject": [
"123456",
"78910",
"99999"
],
"StrObject": "This is a string Object"
}
}

After fix:

{
"DictObject": {
"JObject": [
""TestValue1": 123456",
""TestValue2": 78910",
""TestValue3": 99999"
],
"StrObject": "This is a string Object"
},
"RandomString": "A quick brown fox jumped over the lazy dog"
}

iSazonov
iSazonov previously approved these changes Oct 18, 2017
Copy link
Collaborator

@iSazonov iSazonov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leave a comment

@iSazonov iSazonov requested a review from markekraus October 18, 2017 10:40
Copy link
Contributor

@markekraus markekraus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure this is doing what it is supposed to. Looking at the issue, The expected behavior to should be:

{
  "RandomString": "A quick brown fox jumped over the lazy dog",
  "DictObject": {
    "JObject": {
      "TestValue1": "123456",
      "TestValue2": "78910",
      "TestValue3": "99999"
    },
    "StrObject": "This is a string Object"
  }
}

instead, I'm seeing this:

{
  "RandomString": "A quick brown fox jumped over the lazy dog",
  "DictObject": {
    "JObject": [
      "\"TestValue1\": 123456",
      "\"TestValue2\": 78910",
      "\"TestValue3\": 99999"
    ],
    "StrObject": "This is a string Object"
  }
}

Instead of being an Dictionary of key/value pairs, it's actually an array strings that are escaped representations of JSON key/value pairs.

Is the intent to serialize Newtonsoft.Json.Linq.Jproperty as string representations of JSON or to serialize them as a dictionary?

@iSazonov iSazonov dismissed their stale review October 18, 2017 11:29

I agree that Jproperty should be serialized as a dictionary not string.

@chunqingchen
Copy link
Contributor Author

@markekraus @iSazonov Technically Jproperty cannot be equal to dictionary as it allows null value as key, while dictionary won't.

Copy link
Contributor

@markekraus markekraus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

null keys in ConvertTo-Json should not be an issue

else if (obj is Newtonsoft.Json.Linq.JProperty)
{
rv = obj.ToString();
}
Copy link
Contributor

@markekraus markekraus Oct 18, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe change it to

            else if (obj is Newtonsoft.Json.Linq.JObject jObject)
            {
                rv = jObject.ToObject<Dictionary<object,object>>();
            }

I tested that and it can support the following:

$EgJObject = New-Object -TypeName Newtonsoft.Json.Linq.JObject
$EgJObject.Add("TestValue1", "123456")
$EgJObject.Add("TestValue2", "78910")
$EgJObject.Add("TestValue3", "99999")
$EgJObject.Add($null, "88888")
$EgJObject.Add("StringTest", "'StringToken'")
$EgJObject.Add("HashTest", '{ "innerkey": "innervalue" }')
$dict = @{}
$dict.Add('JObject', $EgJObject)
$dict.Add('StrObject', 'This is a string Object')
$properties = @{'DictObject' = $dict; 'RandomString' = 'A quick brown fox jumped over the lazy dog'}
$object = New-Object -TypeName psobject -Property $properties
$object | ConvertTo-Json

result

{
  "DictObject": {
    "StrObject": "This is a string Object",
    "JObject": {
      "TestValue1": 123456,
      "TestValue2": 78910,
      "TestValue3": 99999,
      "": 88888,
      "StringTest": "StringToken",
      "HashTest": {
        "innerkey": "innervalue"
      }
    }
  },
  "RandomString": "A quick brown fox jumped over the lazy dog"
}

The null key value should only be an issue in the ConvertFrom-Json cmdlet. Since a null value key is valid JSON, we don't need to worry about it in this direction with ConvertTo-Json`.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting. Newtonsoft.Json has large internal capabilities for serialization and deserialization - it would make sense to use them in future.

Copy link
Contributor

@markekraus markekraus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please update tests.

$jsonFormat.contains("TestValue2") | Should Be True
$jsonFormat.contains("78910") | Should Be True
$jsonFormat.contains("TestValue3") | Should Be True
$jsonFormat.contains("99999") | Should Be True
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since these tests failed to detect the issue of the object being properly transformed, i think he tests should be modified in some way that makes it more apparent if the wrong serialization took place.

@chunqingchen
Copy link
Contributor Author

@markekraus your solution works better and your comment is resolved !

@TravisEz13
Copy link
Member

Please use the present tense, imperative style for commit messages and title per Contribution Guide

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Usualy we use the pattern to get good error message from Pester:

$jsonFormat | Should Match '"TestValue1": 123456')

@chunqingchen chunqingchen changed the title Newtonsoft.Json.Linq.Jproperty should be converted to Json properly Jproperty should be converted to Json format properly Nov 1, 2017
@chunqingchen
Copy link
Contributor Author

@iSazonov your comment is resolved.

Copy link
Contributor

@markekraus markekraus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@TravisEz13
Copy link
Member

should is not imperative.
Please use the present tense, imperative style for commit messages and title per Contribution Guide

@markekraus
Copy link
Contributor

@chunqingchen suggested title: Add Jobject serialization support to ConvertTo-Json

@chunqingchen chunqingchen changed the title Jproperty should be converted to Json format properly Add Jobject serialization support to ConvertTo-Json Nov 2, 2017
@chunqingchen
Copy link
Contributor Author

@TravisEz13 @markekraus title updated

@TravisEz13 TravisEz13 merged commit 36b600d into PowerShell:master Nov 3, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ConvertTo-JSON: Nested Object of type Newtonsoft.Json.Linq.JObject not converted to Json properly

4 participants