Dim serialized = Newtonsoft.Json.JsonConvert.SerializeObject(gridOrderNewState)
Dim gridOrderNewstate2 = Newtonsoft.Json.JsonConvert.DeserializeObject(Of gridTradingState)(serialized)
The result is almost empty version of gridOrderNewstate2
This is the value of serialized
{
"bidInBase":0.99055,
"askInBase":0.99333,
"high":0.99448,
"low":0.97528,
"dateSinceLastTransactions":"2022-11-14T21:04:34.0103292+07:00",
"suggestedLow":0.0,
"suggestedhigh":0.0,
"Orders":[
{
"time":"2022-11-14T13:09:54",
"id":"227286807874",
"customIdentifier":"t-FraxTest",
"amountOfQuoteCurrencyBeingOrdered":6.25,
"priceInBasecoin":1.0,
"marketString":"gate",
"Base":"USDT",
"Quote":"FRAX",
"isSellingInsteadOfBuying":true,
"marketURL":"https://gate.io/trade/frax_usdt"
},
{
"time":"2022-11-14T13:09:54",
"id":"227286807867",
"customIdentifier":"t-FraxTest",
"amountOfQuoteCurrencyBeingOrdered":6.263,
"priceInBasecoin":0.99778,
"marketString":"gate",
"Base":"USDT",
"Quote":"FRAX",
"isSellingInsteadOfBuying":true,
"marketURL":"https://gate.io/trade/frax_usdt"
},
{
"time":"2022-11-14T13:09:54",
"id":"227286807859",
"customIdentifier":"t-FraxTest",
"amountOfQuoteCurrencyBeingOrdered":6.277,
"priceInBasecoin":0.99556,
"marketString":"gate",
"Base":"USDT",
"Quote":"FRAX",
"isSellingInsteadOfBuying":true,
"marketURL":"https://gate.io/trade/frax_usdt"
},
{
"time":"2022-11-14T13:09:54",
"id":"227286807851",
"customIdentifier":"t-FraxTest",
"amountOfQuoteCurrencyBeingOrdered":6.291,
"priceInBasecoin":0.99333,
"marketString":"gate",
"Base":"USDT",
"Quote":"FRAX",
"isSellingInsteadOfBuying":true,
"marketURL":"https://gate.io/trade/frax_usdt"
},
{
"time":"2022-11-14T13:09:54",
"id":"227286807835",
"customIdentifier":"t-FraxTest",
"amountOfQuoteCurrencyBeingOrdered":6.334,
"priceInBasecoin":0.98667,
"marketString":"gate",
"Base":"USDT",
"Quote":"FRAX",
"isSellingInsteadOfBuying":false,
"marketURL":"https://gate.io/trade/frax_usdt"
},
{
"time":"2022-11-14T13:09:54",
"id":"227286807823",
"customIdentifier":"t-FraxTest",
"amountOfQuoteCurrencyBeingOrdered":6.348,
"priceInBasecoin":0.98444,
"marketString":"gate",
"Base":"USDT",
"Quote":"FRAX",
"isSellingInsteadOfBuying":false,
"marketURL":"https://gate.io/trade/frax_usdt"
},
{
"time":"2022-11-14T13:09:54",
"id":"227286807816",
"customIdentifier":"t-FraxTest",
"amountOfQuoteCurrencyBeingOrdered":6.363,
"priceInBasecoin":0.98222,
"marketString":"gate",
"Base":"USDT",
"Quote":"FRAX",
"isSellingInsteadOfBuying":false,
"marketURL":"https://gate.io/trade/frax_usdt"
},
{
"time":"2022-11-14T13:09:54",
"id":"227286807762",
"customIdentifier":"t-FraxTest",
"amountOfQuoteCurrencyBeingOrdered":6.377,
"priceInBasecoin":0.98,
"marketString":"gate",
"Base":"USDT",
"Quote":"FRAX",
"isSellingInsteadOfBuying":false,
"marketURL":"https://gate.io/trade/frax_usdt"
}
]
}
So obviously something is there.
Yet I cannot deserialize into the same object class.
This is the class by the way
Class gridTradingState
ReadOnly Property bidInBase As Decimal
ReadOnly Property askInBase As Decimal
ReadOnly Property high As Decimal
ReadOnly Property low As Decimal
ReadOnly Property dateSinceLastTransactions As Date
ReadOnly Property suggestedLow As Decimal
ReadOnly Property suggestedhigh As Decimal
ReadOnly Property Orders As OrderAlreadyPlacedAtanExchange()
Public Shared Function creategridTradingOldState(market As MarketPairInanExchange, ordersInp As OrderAlreadyPlacedAtanExchange()) As gridTradingState
Dim currentState = New gridTradingState
'currentState._bidInBase = market.askbidInBase(False)
'currentState._askInBase = market.askbidInBase(True)
currentState._bidInBase = market.bidInBaseCoin
currentState._askInBase = market.askInBaseCoin
currentState._high = market.highInBaseCoin
currentState._low = market.lowInBaseCoin
currentState._Orders = ordersInp
currentState._dateSinceLastTransactions = Now
Return currentState
End Function
Public Sub updateSuggestedLowandHigh(suggestedLowNew As Decimal, suggestedHighNew As Decimal)
_suggestedLow = suggestedLowNew
_suggestedhigh = suggestedHighNew
End Sub
End Class
Someone asked for a minimally reproduceable sample. I remove orders. The content of serialize becomes
{
"bidInBase": 0.98735,
"askInBase": 0.9918,
"high": 0.99448,
"low": 0.97528,
"dateSinceLastTransactions": "2022-11-14T22:47:47.5532599+07:00",
"suggestedLow": 0.0,
"suggestedhigh": 0.0
}
And the problem stays. It seems that dbc is onto something
Related
Im trying to import a json to datagridview in vb.net.
{ "data":
{ "docdata":
{ "Join": [
{ "Allocated": [
{ "dt": "19-04-2022", },
{ "dt": "30-04-2022", },
{ "dt": "03-05-2022", },
{ "dt": "13-06-2022", },
{ "dt": "07-07-2022", }
]
}
}
}
}
the first "dt" value which is 19-04-2-22 is not being adding to the datagridview, instead values are being inserted from 30-04-2022
For i = 0 To Joincount - 1
For j = 0 To jsonobject.SelectToken("data.docdata.Join")(i)("Allocated").Count - 1
FrmStart.DataGridView1.Rows(i).Cells(0).Value = jsonobject.SelectToken("data.docdata.Join")(i)("Allocated")(j)("dt")
'Console.WriteLine(jsonobject.SelectToken("data.docdata.Join")(i)("Allocated")(j)("dt"))
Next
' crow += 1
FrmStart.DataGridView1.Rows.Add()
Next
In the debug window, "console.writeline" returns correct values. It is printing the first record, which is dated 19-04-2022. However, it is not inserting the same in gridview.
I'm a beginner at coding. and my way of thinking is also in its early stages, so please advise me on the best way to deal with it.
Thank you all for your efforts.#user21031252, the problem still exists even with that method however it got fixed if i changed coding.
For i = 0 To Joincount - 1
For j = 0 To jsonobject.SelectToken("data.docdata.Join")(i)("Allocated").Count - 1
jdate = jsonobject.SelectToken("data.docdata.Join")(i)("Allocated")(j)("dt")
Next
FrmStart.DataGridView1.Rows.Add(Jdate)
Next
Hopefully this will help others working with json objects.
Suggested solution after correcting the json string:
Imports Newtonsoft.Json.Linq
Public Class Form1
Private Sub btnTest_Click(sender As Object, e As EventArgs) Handles btnTest.Click
Dim JsonData As String = "
{ ""data"":
{ ""docdata"":
{ ""Join"":
[
{ ""Allocated"":
[
{ ""dt"": ""19-04-2022"", },
{ ""dt"": ""30-04-2022"", },
{ ""dt"": ""03-05-2022"", },
{ ""dt"": ""13-06-2022"", },
{ ""dt"": ""07-07-2022"", }
]
}
]
}
}
} "
Dim JsonObject As JObject = JObject.Parse(JsonData)
For i = 0 To JsonObject.Count - 1
For j = 0 To JsonObject.SelectToken("data.docdata.Join")(i)("Allocated").Count - 1
DataGridView1.Rows.Add(JsonObject.SelectToken("data.docdata.Join")(i)("Allocated")(j)("dt"))
Next
Next
End Sub
End Class
Public Class Allocated
Public Property dt As String
End Class
Public Class Join
Public Property Allocated As Allocated()
End Class
Public Class Docdata
Public Property Join As Join()
End Class
Public Class Data
Public Property docdata As Docdata
End Class
Public Class Example
Public Property data As Data
End Class
Hello I use laravel 8 and backpack 4.1. I get an error: Property not found in \Illuminate\Contracts\Auth\Authenticatable|null, I have user_id in the table 'tenants'. Has somebody an idea, why the variable $ccu is null.
User.php:
public static function getUser()
{
return Auth::guard('backpack')->user();
}
public function tenant(): BelongsTo
{
return $this->belongsTo(Tenant::class);
}
Tenant.php:
vpublic function ccus(): HasMany
{
return $this->hasMany(Ccu::class);
}
public function users():hasMany
{
return $this->hasMany(User::class, 'user_id');
}
DashboardUserController:
public function index()
{
if (backpack_user()->hasRole('admin')) {
$this->data['title'] = trans('backpack::base.dashboard');
$this->data['breadcrumbs'] = [
trans('backpack::crud.admin') => backpack_url('dashboard'),
trans('backpack::base.dashboard') => false,
];
return view('dashboard', $this->data);
} else {
$user=User::getUser();
$ccu = $user->tenant->ccus()->get();
$ccuDiagram = new CcuDiagram($ccu);
$dataForGauge = CcuDiagram::getData($ccu);
$service = Service::find(1);
return view('ccu', ["dataForGauge" => $dataForGauge, "service" => $service]);
}
}
Ccu.php
public function tenant(): HasOne
{
return $this->hasOne(Tenant::Class);
}
Look at Dataset.collectFromPlan
private def collectFromPlan(plan: SparkPlan): Array[T] = {
val objProj = GenerateSafeProjection.generate(deserializer :: Nil)
plan.executeCollect().map { row =>
objProj(row).get(0, null).asInstanceOf[T]
}
}
the generated code for objProj is:
class SpecificSafeProjection extends org.apache.spark.sql.catalyst.expressions.codegen.BaseProjection {
private Object[] references;
private InternalRow mutableRow;
private Object[] values;
private org.apache.spark.sql.types.StructType schema;
public SpecificSafeProjection(Object[] references) {
this.references = references;
mutableRow = (InternalRow) references[references.length - 1];
schema = (org.apache.spark.sql.types.StructType) references[0];
}
public void initialize(int partitionIndex) {
}
public java.lang.Object apply(java.lang.Object _i) {
........
final org.apache.spark.sql.Row value = new org.apache.spark.sql.catalyst.expressions.GenericRowWithSchema(values, schema);
if (false) {
mutableRow.setNullAt(0);
} else {
mutableRow.update(0, value);
}
return mutableRow;
}
}
And my question is:
The generated method SpecificSafeProjection.apply returns mutableRow: InternalRow who wraps value:GenericRowWithSchema, why not return value:GenericRowWithSchema directly??
I am playing around with Spring Data Solr with Schemaless Solr. There are some dots I am not able to connect: when and how are the schema fields being created?
The following page states
Automatic schema population will inspect your domain types whenever the applications context is refreshed and populate new fields to your index based on the properties configuration. This requires solr to run in Schemaless Mode.
Use #Indexed to provide additional details like specific solr types to use.
It also goes to show a curl request:
// curl ../solr/collection1/schema/fields -X POST -H 'Content-type:application/json'
However, when I run a simple example with field annotated with #Indexed, I do not see the /schema/fields API being called on SOLR. How are these fields created?
The reason I am asking is that they seem to be automatically created with multiValued=true. I did not see the #Indexed annotation taking multiValued as a parameter. How can I force Spring Data Solr to declare fields as non-multiValued when it creates them?
Now, all of this is really to resolve this exception I am seeing.
java.lang.IllegalArgumentException: [Assertion failed] - this argument is required; it must not be null
at org.springframework.util.Assert.notNull(Assert.java:115)
at org.springframework.util.Assert.notNull(Assert.java:126)
at org.springframework.data.solr.core.convert.MappingSolrConverter$SolrPropertyValueProvider.readValue(MappingSolrConverter.java:426)
at org.springframework.data.solr.core.convert.MappingSolrConverter$SolrPropertyValueProvider.readCollection(MappingSolrConverter.java:601)
at org.springframework.data.solr.core.convert.MappingSolrConverter$SolrPropertyValueProvider.readValue(MappingSolrConverter.java:440)
at org.springframework.data.solr.core.convert.MappingSolrConverter$SolrPropertyValueProvider.readValue(MappingSolrConverter.java:412)
at org.springframework.data.solr.core.convert.MappingSolrConverter$SolrPropertyValueProvider.getPropertyValue(MappingSolrConverter.java:395)
at org.springframework.data.solr.core.convert.MappingSolrConverter.getValue(MappingSolrConverter.java:206)
at org.springframework.data.solr.core.convert.MappingSolrConverter$1.doWithPersistentProperty(MappingSolrConverter.java:194)
at org.springframework.data.solr.core.convert.MappingSolrConverter$1.doWithPersistentProperty(MappingSolrConverter.java:186)
at org.springframework.data.mapping.model.BasicPersistentEntity.doWithProperties(BasicPersistentEntity.java:309)
at org.springframework.data.solr.core.convert.MappingSolrConverter.read(MappingSolrConverter.java:186)
at org.springframework.data.solr.core.convert.MappingSolrConverter.read(MappingSolrConverter.java:174)
at org.springframework.data.solr.core.convert.MappingSolrConverter.read(MappingSolrConverter.java:149)
at org.springframework.data.solr.core.SolrTemplate.convertSolrDocumentListToBeans(SolrTemplate.java:560)
at org.springframework.data.solr.core.SolrTemplate.convertQueryResponseToBeans(SolrTemplate.java:552)
at org.springframework.data.solr.core.SolrTemplate.createSolrResultPage(SolrTemplate.java:369)
at org.springframework.data.solr.core.SolrTemplate.doQueryForPage(SolrTemplate.java:300)
at org.springframework.data.solr.core.SolrTemplate.queryForPage(SolrTemplate.java:308)
at org.springframework.data.solr.repository.support.SimpleSolrRepository.findAll(SimpleSolrRepository.java:111)
at org.springframework.data.solr.repository.support.SimpleSolrRepository.findAll(SimpleSolrRepository.java:106)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at
My guess is that the exception is happening because values are being returned as a collection?
I tried to step through the code to understand what is happening. The field that is causing problem is "name", the value is [product-1]. The exception is happening when trying to unmarshall a solr document into a POJO.
First we go inside the following method:
private <T> T readValue(Object value, TypeInformation<?> type, Object parent) {
if (value == null) {
return null;
}
Assert.notNull(type);
Class<?> rawType = type.getType();
if (hasCustomReadTarget(value.getClass(), rawType)) {
return (T) convert(value, rawType);
}
Object documentValue = null;
if (value instanceof SolrInputField) {
documentValue = ((SolrInputField) value).getValue();
} else {
documentValue = value;
}
if (documentValue instanceof Collection) {
return (T) readCollection((Collection<?>) documentValue, type, parent);
} else if (canConvert(documentValue.getClass(), rawType)) {
return (T) convert(documentValue, rawType);
}
return (T) documentValue;
}
When calling this method, the value is a collection and the type is java.lang.String. This results in the if(documentValue instanceof Collection) being selected, which results into following method being executed:
private Object readCollection(Collection<?> source, TypeInformation<?> type, Object parent) {
Assert.notNull(type);
Class<?> collectionType = type.getType();
if (CollectionUtils.isEmpty(source)) {
return source;
}
collectionType = Collection.class.isAssignableFrom(collectionType) ? collectionType : List.class;
Collection<Object> items;
if (type.getType().isArray()) {
items = new ArrayList<Object>();
} else {
items = CollectionFactory.createCollection(collectionType, source.size());
}
TypeInformation<?> componentType = type.getComponentType();
Iterator<?> it = source.iterator();
while (it.hasNext()) {
items.add(readValue(it.next(), componentType, parent));
}
return type.getType().isArray() ? convertItemsToArrayOfType(type, items) : items;
}
In this method, we end up calling type.getComponentType(), which returns null and ultimately cause Assert.notNull() to fail.
What am I missing in all this?
My code is as follows. Launch and config class:
#Configuration
#ComponentScan
#EnableAutoConfiguration
#EnableSolrRepositories(schemaCreationSupport=true, basePackages = { "com.example.solrdata" }, multicoreSupport = true)
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Model class:
#SolrDocument(solrCoreName = "collection1")
public class Product {
#Id
String id;
#Indexed
String name;
public Product(String id, String name) {
this.id = id;
this.name = name;
}
public Product() {
super();
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}}
Repository:
public interface ProductRepository extends SolrCrudRepository<Product, String> {}
Test class:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(Application.class)
public class SolrProductRepositoryTest {
#Autowired
private ProductRepository repo;
#Before #After
public void setup(){
repo.deleteAll();
}
#Test
public void testCRUD() {
assertEquals(0, repo.count());
Product product = new Product("1","product-1");
repo.save(product);
assertEquals(1, repo.count());
Product product2 = repo.findOne(product.getId());
assertEquals(product2.getName(), product.getName());
}}
And finally, my POM:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.3.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-solr</artifactId>
</dependency>
</dependencies>
When using Solr 4.10 with the defaults unfortunately the JSONResponseWriter in solrconfig.xml uses text/pain as content type.
<queryResponseWriter name="json" class="solr.JSONResponseWriter">
<str name="content-type">text/plain; charset=UTF-8</str>
</queryResponseWriter>
This causes the content type negotiation of SolrSchemaRequest to silently fail and skip the schema update step - and solr default field type guessing kicks in at that place.
Setting content-type to application/json allows to add fields according to the bean definition.
#SolrDocument(solrCoreName = "collection1")
public static class SomeDomainType {
#Indexed #Id
String id;
#Indexed
String indexedStringWithoutType;
#Indexed(name = "namedField", type = "string", searchable = false)
String justAStoredField;
#Indexed
List<String> listField;
#Indexed(type = "tdouble")
Double someDoubleValue;
}
Before
{
responseHeader: {
status: 0,
QTime: 86
},
fields: [
{
name: "_version_",
type: "long",
indexed: true,
stored: true
},
{
name: "id",
type: "string",
multiValued: false,
indexed: true,
required: true,
stored: true,
uniqueKey: true
}
]
}
After Schema Upate
{
responseHeader: {
status: 0,
QTime: 1
},
fields: [
{
name: "_version_",
type: "long",
indexed: true,
stored: true
},
{
name: "id",
type: "string",
multiValued: false,
indexed: true,
required: true,
stored: true,
uniqueKey: true
},
{
name: "indexedStringWithoutType",
type: "string",
multiValued: false,
indexed: true,
required: false,
stored: true
},
{
name: "listField",
type: "string",
multiValued: true,
indexed: true,
required: false,
stored: true
},
{
name: "namedField",
type: "string",
multiValued: false,
indexed: false,
required: false,
stored: true
},
{
name: "someDoubleValue",
type: "tdouble",
multiValued: false,
indexed: true,
required: false,
stored: true
}
]
}
How can I remove empty array and empty list from a JSON string?
I use vb.net and json.net to make this but json.net can't remove empty array from JSON string. My JSON string is like this:
{
"jsonrpc": "2.0",
"id": 1,
"token": "tikenname",
"method": "task.run",
"params": {
"commandList": [{
"method": "Users.new",
"params": {
"userIds": "userid",
"details": {
"credentials": {
"userName": "user",
"password": "pass"
},
"data": {
"rights": {},
"quota": {
"daily": {
"limit": {}
},
"weekly": {
"limit": {}
},
"monthly": {
"limit": {}
}
},
"wwwFilter": {}
},
"autoLogin": {
"addresses": {},
"addressGroup": {}
},
"vpnAddress": {},
"groups": {}
}
}
},
{
"method": "set.save"
}
]
}
}
for example I want to remove this section from my string
"data": {
"rights": {},
"quota": {
"daily": {
"limit": {}
},
"weekly": {
"limit": {}
},
"monthly": {
"limit": {}
}
},
"wwwFilter": {}
},
"autoLogin": {
"addresses": {},
"addressGroup": {}
},
"vpnAddress": {},
"groups": {}
And here's my class:
Public Class Account
Public Property jsonrpc As String
Public Property id As Integer
Public Property token As String
Public Property method As String
Public Property params As New AccountSetParams
End Class
Public Class AccountSetParams
Public Property commandList As New List(Of AccountSetCommandlist)
End Class
Public Class AccountSetCommandlist
Public Property method As String
Public Property params As New AccountSetUserDetails
End Class
Public Class AccountSetUserDetails
Public Property userIds() As String
Public Property details As New AccountSetDetails
Public Property domainId As String
End Class
Public Class AccountSetDetails
Public Property credentials As New AccountSetCredentials
Public Property fullName As String
Public Property data As New AccountSetData
Public Property autoLogin As New AccountSetAutologin
Public Property vpnAddress As New AccountSetVpnaddress
Public Property groups() As New AccountSetGroup
End Class
...
It does not look like Json.Net provides an easy way to exclude empty lists or arrays like you are describing. Technically, most of the objects that you want to exclude are NOT empty: they contain other objects [that contain other objects ...] that are empty.
So to accomplish this, you will need to use recursive descent to filter out the "non-useful" information. I think probably the best approach is to first load your object graph into a JObject (or JArray), then recursively copy non-empty elements into a new JObject (or JArray), working your way from the deepest levels upward. You can then serialize the copy to get the pared-down JSON you want. This approach will allow you to handle any object structure in a generic manner.
Here is a function that should do the trick:
Function RemoveEmptyChildren(token As JToken) As JToken
If token.Type = JTokenType.Object Then
Dim copy As JObject = New JObject()
For Each prop As JProperty In token.Children(Of JProperty)()
Dim child As JToken = prop.Value
If child.HasValues Then
child = RemoveEmptyChildren(child)
End If
If Not IsEmpty(child) Then
copy.Add(prop.Name, child)
End If
Next
Return copy
ElseIf token.Type = JTokenType.Array Then
Dim copy As JArray = New JArray()
For Each child As JToken In token.Children()
If child.HasValues Then
child = RemoveEmptyChildren(child)
End If
If Not IsEmpty(child) Then
copy.Add(child)
End If
Next
Return copy
End If
Return token
End Function
Function IsEmpty(token As JToken) As Boolean
Return (token.Type = JTokenType.Array And Not token.HasValues) Or
(token.Type = JTokenType.Object And Not token.HasValues) Or
(token.Type = JTokenType.String And token.ToString() = String.Empty) Or
(token.Type = JTokenType.Null)
End Function
Here is a short example demonstrating how to use the function:
Dim jsonString As String = _
"{" + _
"""Int"" : 1," + _
"""String"" : ""Foo""," + _
"""EmptyString"" : """"," + _
"""EmptyArray"" : []," + _
"""EmptyObject"" : {}," + _
"""NullValue"" : null," + _
"""ArrayOfEmptyChildren"" : [ [], {}, """", null ]," + _
"""ChildObjectWithEmptyValues"" : {" + _
"""Array"" : []," + _
"""Object"" : {}," + _
"""Null"" : null," + _
"""String"" : """"" + _
"}," + _
"""Boolean"" : true" + _
"}"
Dim token As JToken = RemoveEmptyChildren(JToken.Parse(jsonString))
Console.WriteLine(token.ToString(Formatting.Indented))
And here is the output of the above example. Notice that only the non-empty information remains.
{
"Int": 1,
"String": "Foo",
"Boolean": true
}
Note: if you are starting from an object instead of a JSON string, you can still use this function. Just replace JToken.Parse(jsonString) in the example above with JToken.FromObject(yourObject).
Also, if you want to change what gets removed or doesn't get removed from the output, you can modify the IsEmpty function to suit your needs.
Hope this helps.