As part of a SSIS (2005) package I am calling a RESTful API through a script component (VB.NET). I am getting the records back OK. The problem I have though is processing the format it comes back in so I can output it (split into the separate output columns) within the data flow and write into a SQL table. Don't know where to start - anyone got any ideas? I have no control over the API so am stuck with this format.
Here is the schema as per the API documentation:
{StatusMessage : <string>, Unit : <string> [ { VehicleID : <int>, RegistrationNumber : <string>, DistanceTravelled : <double>} ] }
And here is a sample of the data returned (it comes back as a single line of text):
{"VehicleDistance":
[
{
"VehicleId":508767,
"RegistrationNumber":"BJ63 NYO",
"DistanceTravelled":0.09322560578584671
},
{
"VehicleId":508788,
"RegistrationNumber":"BJ63 NYL",
"DistanceTravelled":6.1591048240661621
},
{
"VehicleId":508977,
"RegistrationNumber":"PE12 LLC",
"DistanceTravelled":60.975761413574219
},
{
"VehicleId":510092,
"RegistrationNumber":"BJ64 FCY",
"DistanceTravelled":14.369173049926758
},
{
"VehicleId":510456,
"RegistrationNumber":"BJ63 NYY",
"DistanceTravelled":4.04599142074585
},
{
"VehicleId":513574,
"RegistrationNumber":"BL64 AEM",
"DistanceTravelled":302.150390625
}
],
"StatusMessage":null,
"Unit":"imperial",
"HttpStatus":200
}
This is Javscript Object Notation AKA JSON and you need to deserialise it. The problem is that using SSIS is tricky with third party tools that are popular (and fast) but VB.Net actually has a built in class to serialise and deserialise JSON called JavaScriptSerializer
First add a Reference to your project called System.Web.Extensions and then you can use the JavaScriptSerializer to deserialise your JSON.
I've put your JSON in a file for easier handling so first I have to...
Dim sJSON As String = ""
Using swReadFile As New System.IO.StreamReader("E:\JSON.txt")
sJSON = swReadFile.ReadToEnd()
End Using
The rest is the pertinent bit, so first add 2 Imports...
Imports System.Collections.Generic
Imports System.Web.Script.Serialization
Then for example we can...
Dim lvSerializer As JavaScriptSerializer = New JavaScriptSerializer()
lvSerializer.MaxJsonLength = 2147483644
Dim dictParsedJSONPairs As Dictionary(Of String, Object) = lvSerializer.Deserialize(Of Dictionary(Of String, Object))(sJSON)
If dictParsedJSONPairs.ContainsKey("VehicleDistance") AndAlso _
TypeOf dictParsedJSONPairs("VehicleDistance") Is ArrayList Then
Dim ArrayEntries As ArrayList = DirectCast(dictParsedJSONPairs("VehicleDistance"), ArrayList)
For Each ArrayEntry As Object In ArrayEntries
Dim DictEntry As Dictionary(Of String, Object) = DirectCast(ArrayEntry, Dictionary(Of String, Object))
If DictEntry.ContainsKey("VehicleId") Then Console.WriteLine("VehichleId:" & DictEntry("VehicleId"))
Next
End If
If dictParsedJSONPairs.ContainsKey("Unit") Then
Console.WriteLine("Unit is " & dictParsedJSONPairs.Item("Unit"))
End If
Clearly you should research JSON before launching into serious use. The object can be nested JSON (i.e. Dictionary(Of String, Object)), a number of some sort, a string or an ArrayList
It could be a bit late but you may want to have a look at json.net from Newtonsoft (website). The component provided contains .Net 2.0 version.
Using it in a SSIS script task is quite simple. I did it in SSIS2008 based on .Net 3.5 to parse JSON string like below. And according to the document, it should work for .Net 2.0 version as well.
//I assume you had obtained JSON in string format
string JasonBuffer;
//define Json object
JObject jObject = JObject.Parse(JasonBuffer);
//In my example the Json object starts with result
JArray Results = (JArray)jObject["result"];
//loop the result
foreach (JObject Result in Results)
{
//for simple object
JObject joCustomer = (JObject)Result["Customer"];
//do something...
//for complex object continue drill down
foreach (JObject joSection in Result["Sections"])
{
foreach (JObject joDepartment in joSection["Departments"])
{
foreach (JObject joItem in joDepartment["Items"])
{
}
You can find some actual code here: link
Related
The function requires a generic list (of Byte()) to be passed as agrs and I just cannot seem to get anything to add to this list.I require printdata(0) & (1) adding to it.
Dim printdata(1) As String
labelname = "WasNow"
printdata(0) = "9,99"
printdata(1) = "6.99"
Dim args = New List(Of Byte())
args.Add(Convert.ToByte(printdata))
ApplicationContext.CurrentDevice.Printer.Print(labelname, 1, args)
Frmscanprint.Show()
This is the working C# version of the code with only one item to add.
private void printButton_Click(object sender, EventArgs e)
{
try
{
this.printNumber++;
var args = new List<byte[]>() { Encoding.ASCII.GetBytes(string.Format(CultureInfo.InvariantCulture, "Test #{0}", this.printNumber)) };
if (!ApplicationContext.AllDevicesSelected)
{
ApplicationContext.CurrentDevice.Printer.Print("SamplePrint", 1, args);
}
else
{
PrintSampleForEachDevice("SamplePrint", 1, args);
}
}
}
The C# example you provided gets a single string and converts it to a byte array, assigning this array to the newly created list.
Your code is not doing the same thing. You are trying to convert a string array to a byte array. This conversion type is not allowed by the method you are trying to use. Even if it is possible, the result would be a single byte array with the entire content and not an array of byte array.
If you want to do the same thing as the C# code does, you shoud do it for each itm from your string array a time.
If you want to do the same thing as the C# code, you shoud do it for each single item from your string array. For example:
For Each item As String In printdata
args.Add(Encoding.ASCII.GetBytes(item))
Next
I would like to pass a complete JSON object to a java adapter in worklight. This adapter will call multiple other remote resources to fulfill the request. I would like to pass the json structure instead of listing out all of the parameters for a number of reasons. Invoking the worklight procedure works well. I pass the following as the parameter:
{ "parm1": 1, "parm2" : "hello" }
Which the tool is fine with. When it calls my java code, I see a object type of JSObjectConverter$1 being passed. In java debug, I can see the values in the object, but I do not see any documentation on how to do this. If memory serves me, the $1 says that it is an anonymous inner class that is being passed. Is there a better way to pass a json object/structure in adapters?
Lets assume you have this in adapter code
function test(){
var jsonObject = { "param1": 1, "param2" : "hello" };
var param2value = com.mycode.MyClass.parseJsonObject(jsonObject);
return {
result: param2value
};
}
Doesn't really matter where you're getting jsonObject from, it may come as a param from client. Worklight uses Rhino JS engine, therefore com.mycode.MyClass.parseJsonObject() function will get jsonObject as a org.mozilla.javascript.NativeObject. You can easily get obj properties like this
package com.mycode;
import org.mozilla.javascript.NativeObject;
public class MyClass {
public static String parseJsonObject(NativeObject obj){
String param2 = (String) NativeObject.getProperty(obj, "param2");
return param2;
}
}
To better explain what I'm doing here, I wanted to be able to pass a javascript object into an adapter and have it return an updated javascript object. Looks like there are two ways. The first it what I answered above a few days ago with serializing and unserializing the javascript object. The other is using the ScriptableObject class. What I wanted in the end was to use the adapter framework as described to pass in the javascript object. In doing so, this is what the Adapter JS-impl code looks like:
function add2(a) {
return {
result: com.ibm.us.roberso.Calculator.add2(a)
};
The javascript code in the client application calling the above adapter. Note that I have a function to test passing the javascript object as a parameter to the adapter framework. See the invocationData.parameters below:
function runAdapterCode2() {
// x+y=z
var jsonObject = { "x": 1, "y" : 2, "z" : "?" };
var invocationData = {
adapter : "CalculatorAdapter",
procedure : 'add2',
parameters : [jsonObject]
};
var options = {
onSuccess : success2,
onFailure : failure,
invocationContext : { 'action' : 'add2 test' }
};
WL.Client.invokeProcedure(invocationData, options);
}
In runAdapterCode2(), the javascript object is passed as you would pass any parameter into the adapter. When worklight tries to execute the java method it will look for a method signature of either taking an Object or ScriptableObject (not a NativeObject). I used the java reflection api to verify the class and hierarchy being passed in. Using the static methods on ScriptableObject you can query and modify the value in the object. At the end of the method, you can have it return a Scriptable object. Doing this will give you a javascript object back in the invocationResults.result field. Below is the java code supporting this. Please note that a good chunk of the code is there as part of the investigation on what object type is really being passed. At the bottom of the method are the few lines really needed to work with the javascript object.
#SuppressWarnings({ "unused", "rawtypes" })
public static ScriptableObject add2(ScriptableObject obj) {
// code to determine object class being passed in and its heirarchy
String result = "";
Class objClass = obj.getClass();
result = "objClass = " + objClass.getName() + "\r\n";
result += "implements=";
Class[] interfaces = objClass.getInterfaces();
for (Class classInterface : interfaces) {
result += " " + classInterface.getName() ;
}
result += "\r\nsuperclasses=";
Class superClass = objClass.getSuperclass();
while(superClass != null) {
result += " " + superClass.getName();
superClass = superClass.getSuperclass();
}
// actual code working with the javascript object
String a = (String) ScriptableObject.getProperty((ScriptableObject)obj, "z");
ScriptableObject.putProperty((ScriptableObject)obj, "z", new Long(3));
return obj;
}
Note that for javascript object, a numeric value is a Long and not int. Strings are still Strings.
Summary
There are two ways to pass in a javascript object that I've found so far.
Convert to a string in javascript, pass string to java, and have it reconstitute into a JSONObject.
Pass the javascript object and use the ScriptableObject classes to manipulate on the java side.
Total newby question here, I've been struggling with it for hours!
I'm trying to understand how to actually use, and create JSON data. I've been Googling all afternoon and trying to understand what I fine here http://james.newtonking.com/projects/json/help/ having downloaded the Newtonsoft DLLs.
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
using (JsonWriter jsonWriter = new JsonTextWriter(sw))
{
jsonWriter.Formatting = Formatting.Indented;
jsonWriter.WriteStartObject();
jsonWriter.WritePropertyName("CPU");
jsonWriter.WriteValue("Intel");
jsonWriter.WritePropertyName("PSU");
jsonWriter.WriteValue("500W");
jsonWriter.WritePropertyName("Drives");
jsonWriter.WriteStartArray();
jsonWriter.WriteValue("DVD read/writer");
jsonWriter.WriteComment("(broken)");
jsonWriter.WriteValue("500 gigabyte hard drive");
jsonWriter.WriteValue("200 gigabype hard drive");
jsonWriter.WriteEnd();
jsonWriter.WriteEndObject();
}
Should create something that looks like:
{
"CPU": "Intel",
"PSU": "500W",
"Drives": [
"DVD read/writer"
/*(broken)*/,
"500 gigabyte hard drive",
"200 gigabype hard drive" ]
}
and I am sure it does... but how do I view it? How do I turn that into an object that the browser can output.
It seems to me that the first stage I need to resolve is "how to create" JSON files/strings, next stage will be how to actually use them. If it helps answer the question, what I'm aiming for initially is to be able to use AJAX Autocomplete from a search page generated from my MySQL database, I was hoping I could write a simple SQL query and have that returned using something similar to the above, but I'm clearly going about it all wrong!
BTW, the example above is in C#, I have successfully converted the process to VB, as that's what I am using, but any responses would be much appreciated as VB examples!
I came across this post about two years after it was posted, but I had the exact same question and noticed that the question wasn't really answered. To answer OP's question, this will get you the JSON string in his example.
sb.toString()
The upshot is that you need to get the JSON string back to the browser. You can either place it in a javascript variable (be sure to clean up line enders and single quotes if you do this) or pass it back as the result of an ajax query.
We actually use the built-in Javascript serializer since it has support both on the server and the client side and is quite easy to use. Assuming that you have an existing object, this code goes on the server side:
''' <summary>
''' This method safely serializes an object for JSON by removing all of the special characters (i.e. CRLFs, quotes, etc)
''' </summary>
''' <param name="oObject"></param>
''' <param name="fForScript">Set this to true when the JSON will be embedded directly in web page (as opposed to being passed through an ajax call)</param>
''' <returns></returns>
''' <remarks></remarks>
Public Function SerializeObjectForJSON(ByVal oObject As Object, Optional ByVal fForScript As Boolean = False) As String
If oObject IsNot Nothing Then
Dim sValue As String
sValue = (New System.Web.Script.Serialization.JavaScriptSerializer).Serialize(oObject)
If fForScript Then
' If this serialized object is being placed directly on the page, then we need to ensure that its CRLFs are not interpreted literlally (i.e. as the actual JS values)
' If we don't do this, the script will not deserialize correctly if there are any embedded crlfs.
sValue = sValue.Replace("\r\n", "\\r\\n")
' Fix quote marks
Return CleanString(sValue)
Else
Return sValue
End If
Else
Return String.Empty
End If
End Function
On the client side, deserialization is trivial:
// The result should be a json-serialized record
oRecord = Sys.Serialization.JavaScriptSerializer.deserialize(result.value);
Once you have deserialized the object, you can use its properties directly in javascript:
alert('CPU = ' + oRecord.CPU);
In terms of generating the JSON try
public class HardwareInfo
{
[JsonProperty(PropertyName = "CPU")]
public string Cpu { get; set; }
[JsonProperty(PropertyName = "PSU")]
public string Psu { get; set; }
[JsonProperty]
public ICollection<string> Drives { get; set; }
}
public string SerializeHardwareInfo()
{
var info = new HardwareInfo
{
Cpu = "Intel",
Psu = "500W",
Drives = new List<string> { "DVD read/writer", "500 gigabyte hard drive", "200 gigabype hard drive" }
};
var json = JsonConvert.SerializeObject(info, Formatting.Indented);
// {
// "CPU": "Intel",
// "PSU": "500W",
// "Drives": [
// "DVD read/writer",
// "500 gigabyte hard drive",
// "200 gigabype hard drive"
// ]
// }
return json;
}
The formatting argument is optional. Best of luck.
this is the JSON string the data is required in to be sent using a given URL.
$jsonstr = '{"data":
[{
"id":"5",
"owner_id":"0",
"status":"unassigned",
"first_name":"Test",
"last_name":"IS",
"tobacco_user":"",
"date_of_birth":"",
"age":"",
"gender":"",
"email":"lb#you.com",
"zip":"",
"phone":"(210)629-2560",
"phone_type":"cell",
"phone_alt":"",
"phone_alt_type":"",
"product_msip":"",
"product_pdp":"",
"product_sdhv":""
},
I am using VB.net and i need to create this string using VB.net. I tried using namevaluecollection and doing a POST. I also tried making a string and send data using GET. Both failed. how can i do this?
Create an object with property names that are identical to those in your example, use the DataContract and DataMember attributes to mark serialization.
Then use the JavaScriptSerializer to serialize the object into JSON.
you can use the class when you want to work with JavaScript Object Notation (JSON) in managed code.
If you don't want to build an actual class as #Oded recommended you can just hack it together as a string. I usually use a NameValueCollection as you said you tried.
''//Setup some values
Dim NVC As New NameValueCollection()
NVC.Add("id", "5")
NVC.Add("owner_id", "0")
NVC.Add("status", "unassigned")
''//Convert to string
Dim Pairs As New List(Of String)
For Each N As String In NVC.Keys
Pairs.Add(String.Format("""{0}"":""{1}""", N.Replace("""", "\"""), NVC(N).Replace("""", "\""")))
Next
Dim S = Join(Pairs.ToArray(), ",")
S now holds "id":"5","owner_id":"0","status":"unassigned" which you should be able to concat into your bigger JSON string.
I wonder if anyone can help me - I've not done much with reflection but understand the basic principles.
What I'm trying to do:
I'm in the process of developing a class that gathers a lot of information about the local system, network, etc... to be used for automated bug reporting. Instead of having to change my test harness every time I add a new property, I'd (ideally) like to be able to serialise the lot as an XML string and just display that in a textbox.
Unfortunately, the Framework won't use the default XML serializer on read-only properties (which almost all of mine are) as they wouldn't deserialize properly
[Not sure I agree with the assumption that anything serialized must be de-serializable - MS says this is a feature "by design" which I suppose I can understand - Perhaps a tag to indicate that it should be serialized anyway would be advantageous?]
The initial approach was to make properties gettable and settable (with a throw exception on the setter) but the amount of work tidying this up afterwards seems a little excessive and I would want the properties to be read-only in the final version.
What I need help with:
My current plan is to use reflection to recursively iterate through each (public) property of my topmost gathering class. The problem is, the samples I've seen don't handle things recursively. Additionally, I only want to inspect an object's properties if it's in one of my assemblies - Otherwise just call .ToString on it.
If I don't have the inspection limited to my assembly, I assume I'll get (say) a string which then contains a Length which in turn will have .Tostring method...
For the purposes of this project, I can almost guarantee no circular references within my code and as this will only be used as a development tool so I'm not too concerned about it running amok now and then.
I'd appreciate some examples/advice.
Many thanks in advance.
This will hopefully get you started. It prints a tree directly to the console so you'll need to adjust to output XML. Then change the IsMyOwnType method to filter out the assemblies you're interested in, right now it only cares about types in the same assembly as itself.
Shared Sub RecurseProperties(o As Object, level As Integer)
For Each pi As PropertyInfo In o.GetType().GetProperties()
If pi.GetIndexParameters().Length > 0 Then Continue For
Console.Write(New String(" "c, 2 * level))
Console.Write(pi.Name)
Console.Write(" = ")
Dim propValue As Object = pi.GetValue(o, Nothing)
If propValue Is Nothing Then
Console.WriteLine("<null>")
Else
If IsMyOwnType(pi.PropertyType) Then
Console.WriteLine("<object>")
RecurseProperties(propValue, level+1)
Else
Console.WriteLine(propValue.ToString())
End If
End If
Next
End Sub
Shared Function IsMyOwnType(t As Type) As Boolean
Return t.Assembly Is Assembly.GetExecutingAssembly()
End Function
you extension version on c# to use on any object
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
namespace Extensions
{
public static class ObjectExtension
{
public static string ToStringProperties(this object o)
{
return o.ToStringProperties(0);
}
public static string ToStringProperties(this object o, int level)
{
StringBuilder sb = new StringBuilder();
string spacer = new String(' ', 2 * level);
if (level == 0) sb.Append(o.ToString());
sb.Append(spacer);
sb.Append("{\r\n");
foreach (PropertyInfo pi in o.GetType().GetProperties())
{
if (pi.GetIndexParameters().Length == 0)
{
sb.Append(spacer);
sb.Append(" ");
sb.Append(pi.Name);
sb.Append(" = ");
object propValue = pi.GetValue(o, null);
if (propValue == null)
{
sb.Append(" <null>");
} else {
if (IsMyOwnType(pi.PropertyType))
{
sb.Append("\r\n");
sb.Append(((object)propValue).ToStringProperties(level + 1));
} else{
sb.Append(propValue.ToString());
}
}
sb.Append("\r\n");
}
}
sb.Append(spacer);
sb.Append("}\r\n");
return sb.ToString();
}
private static bool IsMyOwnType(Type t)
{
return (t.Assembly == Assembly.GetExecutingAssembly());
}
}
}