[Lift] Re: BSON support in lift-json
Hi, Here's another idea which might work. It is a bit hackish and needs further analysis, but small experiments I did were promising. What if we change JsonAST just a little by adding a new abstract node called JLiteral to represent simple nonstructural types (note, it is sealed). object JsonAST { sealed abstract class JValue sealed abstract class JLiteral extends JValue case class JInt(value: BigInt) extends JLiteral ... } Then in a same source file extend that by adding BSON extensions. object BsonAST { abstract class JObjectId(val id: Long) extends JsonAST.JLiteral ... object JObjectId { def apply(id: Long) = new JObjectId(id) {} def unapply(x: JObjectId): Option[Long] = Some(x.millis) } } Note, BsonAST extension literals are not case classes but abstract classes + manually coded extractors and factories. Now users of basic JSON processing would not need to care about BSON extensions. For them the pattern matcher would work as it works now. For instance exhaustiveness checking still emits warnings if cases are incomplete. BSON users can import BSON extensions and use extractors: import JsonAST._ import BsonAST._ bson map { case JInt(x) = ... case JDate(t) = ... ... } Cheers Joni On Mar 8, 8:38 pm, Ross Mellgren dri...@gmail.com wrote: I personally think hybrid approaches make sense for certain designs even if they are a little odd. My thought originally was having a new member of the ADT which is not final which represents extensions, e.g. JValue \_ JExtension \_ JDate where JExtensions could be ignored or passed through unchanged by most of the stuff, and only special readers/writers would know what to do with them. -Ross On Mar 8, 2010, at 12:45 PM, David Pollak wrote: On Mon, Mar 8, 2010 at 12:50 AM, Joni Freeman freeman.j...@gmail.com wrote: This is a tricky one. The problem with extending the AST is that the AST is implemented as an algebraic data type. And by definition it is not possible to extend such a type. Just throwing an idea out and it's likely a bad one. I ran into a similar issue with Box and chose to do a hybrid (aka Frankenstein) ADT/OO paradigm. Perhaps it's possible to provide subclasses of certain ADT items (e.g., JDate extends JInt) such that if you pattern match on a JInt, you get the millis as long, but if you pattern match against JDate, you get a date extracted if it's the JDate subclass. Once again, it's likely to be a bad idea as it caused a lot of angst in Box and I'm not sure if the paradigm is one that's worth perpetuating. One way to add BSON support is to create a new AST for it which includes all extended literals. Then add a few core functions for that ADT (map, etc.) and maybe a function which can encode BSON as JSON (bvalue.toJson). Encoding BSON as JSON would give some features for free, for instance toXml. Anyway, this approach would probably cause some code duplication between lift-json and lift-bson. Converting the JSON AST to an object oriented design would be another approach. Then adding new AST nodes would not be a problem. But that would be a huge change to the lib. Probably too big at this phase. Since BSON is a superset of JSON we could refactor current lift-json to be lift-bson and then implement lift-json on top of it. On a cursory look this feels cleanest but there might be some performance penalties for normal JSON processing due to conversions. To be honest, I'm not yet sure what would be the best approach. Cheers Joni On Mar 5, 10:08 pm, Ross Mellgren dri...@gmail.com wrote: The JSON stuff is mostly just an AST and encoding/decoding from the JSON wire format is almost just an addon. Then, it would be a matter of adding AST objects for those new things. Could be a use for phantom types ;-) I'd be interested to hear Joni's view on how it might fit, since he's the most familiar. -Ross On Mar 5, 2010, at 1:26 PM, Tim Nelson wrote: I definitely agree with keeping the BSON code separate or possibly having a strict JSON mode. Tim On Fri, Mar 5, 2010 at 12:13 PM, Timothy Perrett timo...@getintheloop.eu wrote: Probably a sub-ordinate module would be preferable... one that builds on the lift-json stuff and doesn't pollute the normal JSON usage. Joni, what are your thoughts? Cheers, Tim On 5 Mar 2010, at 17:59, Tim Nelson wrote: I finally had the opportunity to look into the couchdb code and I must say it is rather impressive. I would like to utilize the code in JSONRecord.scala in scamongo [1]. However, MongoDB uses a variation of JSON they call BSON, which they actually just published a spec [2] for, due to interest outside of MongoDB. Basically, it adds support for date, ObjectId [3], binary data, regular expressions, and code (JavaScript) data types. My question is, what would it take to add support
[Lift] Re: BSON support in lift-json
This is a tricky one. The problem with extending the AST is that the AST is implemented as an algebraic data type. And by definition it is not possible to extend such a type. One way to add BSON support is to create a new AST for it which includes all extended literals. Then add a few core functions for that ADT (map, etc.) and maybe a function which can encode BSON as JSON (bvalue.toJson). Encoding BSON as JSON would give some features for free, for instance toXml. Anyway, this approach would probably cause some code duplication between lift-json and lift-bson. Converting the JSON AST to an object oriented design would be another approach. Then adding new AST nodes would not be a problem. But that would be a huge change to the lib. Probably too big at this phase. Since BSON is a superset of JSON we could refactor current lift-json to be lift-bson and then implement lift-json on top of it. On a cursory look this feels cleanest but there might be some performance penalties for normal JSON processing due to conversions. To be honest, I'm not yet sure what would be the best approach. Cheers Joni On Mar 5, 10:08 pm, Ross Mellgren dri...@gmail.com wrote: The JSON stuff is mostly just an AST and encoding/decoding from the JSON wire format is almost just an addon. Then, it would be a matter of adding AST objects for those new things. Could be a use for phantom types ;-) I'd be interested to hear Joni's view on how it might fit, since he's the most familiar. -Ross On Mar 5, 2010, at 1:26 PM, Tim Nelson wrote: I definitely agree with keeping the BSON code separate or possibly having a strict JSON mode. Tim On Fri, Mar 5, 2010 at 12:13 PM, Timothy Perrett timo...@getintheloop.eu wrote: Probably a sub-ordinate module would be preferable... one that builds on the lift-json stuff and doesn't pollute the normal JSON usage. Joni, what are your thoughts? Cheers, Tim On 5 Mar 2010, at 17:59, Tim Nelson wrote: I finally had the opportunity to look into the couchdb code and I must say it is rather impressive. I would like to utilize the code in JSONRecord.scala in scamongo [1]. However, MongoDB uses a variation of JSON they call BSON, which they actually just published a spec [2] for, due to interest outside of MongoDB. Basically, it adds support for date, ObjectId [3], binary data, regular expressions, and code (JavaScript) data types. My question is, what would it take to add support to lift-json for these other data types? Is this even feasible? Thanks, Tim [1]http://github.com/eltimn/scamongo [2]http://bsonspec.org/ [3]http://www.mongodb.org/display/DOCS/Object+IDs -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group athttp://groups.google.com/group/liftweb?hl=en. -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group athttp://groups.google.com/group/liftweb?hl=en. -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group athttp://groups.google.com/group/liftweb?hl=en. -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
[Lift] Re: Lift security vulnerability
Note, it is very easy to clean up the JSON before rendering by using 'map' function: json map { case JString(s) = JString(sripOutBinaryChars(s)) case x = x } (You just need to implement that sripOutBinaryChars function...). Cheers Joni On Mar 5, 8:26 pm, Dano olearydani...@gmail.com wrote: I think I would like to amend my last post by asking if it is possible that the lift-jsonlibrary support the ability to strip out binary characters since many times an application uses the results ofJSON operations to render back to the client. Thanks. Dan On Mar 5, 9:53 am, Dano olearydani...@gmail.com wrote: I can reproduce it in our application, but I think it is not necessarily due to Lift. This is what I am trying to sort out. We have client-side javascript which is sendingJSONcommands to the server and things blow up once things come back from the server. In this case, Lift is not responsible for the rendering so I would say this is an application issue. I am poking at the demo lift application to try to flush out issues common to the group and understand what is a framework issue and what needs to be addressed by the application. Thanks. Dan On Mar 5, 9:47 am, Naftoli Gugenheim naftoli...@gmail.com wrote: Can you reproduce the vulnerability in your own M3 app? - Danoolearydani...@gmail.com wrote: I would never claim to be astute. However, I did observe that demo.liftweb.net is now built using 2.0-M3 as is clearly listed at the bottom of the page. I also observed that the Wizard example is still broken (paste binary characters into 'First Name' and then click the Next button). I have not yet registered for an account with Assembla but would be happy to file the bug. Dan On Mar 4, 7:33 pm, Ross Mellgren dri...@gmail.com wrote: Check dpp's response as of 8:01 -Ross On Mar 4, 2010, at 7:49 PM, Naftoli Gugenheim wrote: What version is the demo running? - Danoolearydani...@gmail.com wrote: Just saw that Lift 2.0-M3 was released. I looked to see if the vulnerability was still present in demo.liftweb.net and I am still able to generate exceptions in the browser when I paste binary characters in the textfields for the Wizard, Wizard Challenge, and Arc Challenge examples in the Misc section. Don't know if this remaining problem is supposed to be handled by the application or framework, but thought I would make a post to alert the group. Dan On Feb 24, 11:49 am, Dano olearydani...@gmail.com wrote: The recent scala days conference activity may have cause the updates to this thread to escape notice. Just wondering if there is concern about the remaining binary character problems I noted in my prior post. Thanks in advance. Dan On Feb 22, 1:34 pm, Dano olearydani...@gmail.com wrote: More information on this in case anyone is interested. If you go to theliftdemo website, it appears the issue with characters is mostly addressed except for the Misc code section. Specifically, the Wizard, Wizard Challenge and Arc Challenge #1 examples will generate XML parsing errors. For these problems, I am not sure if the issue if the example or the framework. If the issue is with the example, it would be good to know whatLiftapps need to do to avoid getting bitten by binary characters entered into form fields. Thanks in advance. Dan On Feb 17, 11:06 am, Dano olearydani...@gmail.com wrote: Hello, I was wondering if the fix for the control characters issue was included in 2.0-M2. I just did a test with ourLiftapplication built with 2.0-M2 and I am still seeing problems (i.e. javascript exceptions - NS_ERROR_INVALID_POINTER). Thanks in advance. Dan On Feb 3, 9:08 am, David Pollak feeder.of.the.be...@gmail.com wrote: Thanks for pointing that out. There are other problems as well... I'll fix them (in both the Scala andLiftdiffs) On Wed, Feb 3, 2010 at 7:39 AM, Feng Zhang sharpzh...@gmail.com wrote: I found that in the fix, \n is changed to \t, while \t to \n. Is this desired behavior? Thank you, Feng On Wed, Feb 3, 2010 at 9:20 AM, Indrajit Raychaudhuri indraj...@gmail.com wrote: 1. Fix in head/master (2.0-SNAPSHOT) and prepone 2.0-M2. 2. Backport in 1.0.x branch and spin 1.0.4. We haven't marked 1.0.x 'unsupported' yet. Forcing apps to move to 2.0-M2 just for this vulnerability fix isn't fun. Cheers, Indrajit On 03/02/10 3:34 PM, Timothy Perrett wrote: +1 Fix it in head, no need to back-port; M2 is only around the corner. Cheers, Tim On 3 Feb 2010, at 09:49, Jeppe Nejsum Madsen wrote:
[Lift] Re: JSON help...
Hi David, Does this work? for { user - WorkerMgr.find(UserId(user)) ?~ User not found json - r.json JField(messageId, JInt(messageId)) - json JField(timestamp, JInt(timemillis)) - json } yield .. Cheers Joni On Mar 4, 9:28 pm, David Pollak feeder.of.the.be...@gmail.com wrote: Folks, I'm working on parsing through some JSON that's posted/put as part of a request. I'd like to find the messageId field and only get it if its type is JInt. I'm doing this within a for comprehension that has a Box at the top of it, so the resulting expression must play well with Box. What I've got is: for { user - WorkerMgr.find(UserId(user)) ?~ User not found json - r.json (_, messageJson) - (json \ classOf[JField]).find(_._1 == messageId) messageId - Box.asA[JInt](messageJson) (_, timemillisJson) - (json \ classOf[JField]).find(_._1 == timestamp) timemillis - Box.asA[JInt](timemillisJson) } yield ... The lines that look for messageId and timestamp and insure they are JInts are kinda verbose. Is there a better way to do what I'm trying to do? Thanks, David -- Lift, the simply functional web frameworkhttp://liftweb.net Beginning Scalahttp://www.apress.com/book/view/1430219890 Follow me:http://twitter.com/dpp Surf the harmonics -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
[Lift] Re: JSON help...
Tried it myself and that version does not work. You probably need nested for-comprehension which parses the JSON: for { user - WorkerMgr.find(UserId(user)) ?~ User not found json - r.json data - Box(for { JField(messageId, JInt(messageId)) - json JField(timestamp, JInt(timemillis)) - json } yield (messageId, timemillis)) } yield ... Cheers Joni On Mar 4, 9:55 pm, Joni Freeman freeman.j...@gmail.com wrote: Hi David, Does this work? for { user - WorkerMgr.find(UserId(user)) ?~ User not found json - r.json JField(messageId, JInt(messageId)) - json JField(timestamp, JInt(timemillis)) - json } yield .. Cheers Joni On Mar 4, 9:28 pm, David Pollak feeder.of.the.be...@gmail.com wrote: Folks, I'm working on parsing through some JSON that's posted/put as part of a request. I'd like to find the messageId field and only get it if its type is JInt. I'm doing this within a for comprehension that has a Box at the top of it, so the resulting expression must play well with Box. What I've got is: for { user - WorkerMgr.find(UserId(user)) ?~ User not found json - r.json (_, messageJson) - (json \ classOf[JField]).find(_._1 == messageId) messageId - Box.asA[JInt](messageJson) (_, timemillisJson) - (json \ classOf[JField]).find(_._1 == timestamp) timemillis - Box.asA[JInt](timemillisJson) } yield ... The lines that look for messageId and timestamp and insure they are JInts are kinda verbose. Is there a better way to do what I'm trying to do? Thanks, David -- Lift, the simply functional web frameworkhttp://liftweb.net Beginning Scalahttp://www.apress.com/book/view/1430219890 Follow me:http://twitter.com/dpp Surf the harmonics -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
[Lift] Re: serializing and deserializing a json object through Lift-JSON
Ok, this was yet another bug in serialization code. It is now fixed and should be in next snapshot build. Deserializing null values were not supported. Note a recommended way is to use Option for optional values. This would've worked: case class X(yy: Option[Y]) case class Y(ss: String) from(to(X(None))) It makes me a bit sad that both Scala and JSON support null values... Cheers Joni On Feb 20, 8:13 am, Ali saleh...@gmail.com wrote: Thanks for your reply. Actually I was trying to build an exception I am receiving in our product. case class X(yy:Y) case class Y(ss:String) def from(in:String):X={ implicit val formats = net.liftweb.json.DefaultFormats import net.liftweb.json.JsonAST._ import net.liftweb.json.Extraction._ import net.liftweb.json.Printer._ net.liftweb.json.Serialization.read[X](in) } def to(in:X):String={ implicit val formats = net.liftweb.json.DefaultFormats import net.liftweb.json.JsonAST._ import net.liftweb.json.Extraction._ import net.liftweb.json.Printer._ compact(render(decompose(in))) } val sample = new X(null) val sample2=from(to(sample)) and I am getting, net.liftweb.json.MappingException: Did not find value which can be converted into java.lang.String at net.liftweb.json.Meta$.fail(Meta.scala:99) at net.liftweb.json.Extraction$.convert(Extraction.scala:280) at net.liftweb.json.Extraction$.build$1(Extraction.scala:216) at net.liftweb.json.Extraction$$anonfun$newInstance $1$1.apply(Extraction.scala:199) at net.liftweb.json.Extraction$$anonfun$newInstance $1$1.apply(Extraction.scala:199) at scala.List.map(List.scala:812) I appreciate your comment, Thanks, -A On Feb 20, 12:10 am, Joni Freeman freeman.j...@gmail.com wrote: Is X perhaps an inner class? Inner class has an implicit reference to outer instance. Serializing those is not supported. If so, please move definition of X outside of class. Cheers Joni On Feb 20, 12:16 am, Ali saleh...@gmail.com wrote: Hi, I am wondering, could you please let me know what is wrong in the following code: case class X(vv:String) val sample = new X(A) implicit val formats = net.liftweb.json.DefaultFormats import net.liftweb.json.JsonAST._ import net.liftweb.json.Extraction._ import net.liftweb.json.Printer._ def from(in:String):X=net.liftweb.json.Serialization.read[X](in) def to(in:X):String=compact(render(decompose(in))) val sample2=from(to(sample)) sample2 must_== sample I am getting java.util.NoSuchElementException: key not found: $outer Thanks, -A -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
[Lift] Re: serializing and deserializing a json object through Lift-JSON
Hi, Can't reproduce that. Those lines should work just fine. From which line do you get that exception (please attach full stack trace too)? Cheers Joni On Feb 20, 12:16 am, Ali saleh...@gmail.com wrote: Hi, I am wondering, could you please let me know what is wrong in the following code: case class X(vv:String) val sample = new X(A) implicit val formats = net.liftweb.json.DefaultFormats import net.liftweb.json.JsonAST._ import net.liftweb.json.Extraction._ import net.liftweb.json.Printer._ def from(in:String):X=net.liftweb.json.Serialization.read[X](in) def to(in:X):String=compact(render(decompose(in))) val sample2=from(to(sample)) sample2 must_== sample I am getting java.util.NoSuchElementException: key not found: $outer Thanks, -A -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
[Lift] Re: serializing and deserializing a json object through Lift-JSON
Is X perhaps an inner class? Inner class has an implicit reference to outer instance. Serializing those is not supported. If so, please move definition of X outside of class. Cheers Joni On Feb 20, 12:16 am, Ali saleh...@gmail.com wrote: Hi, I am wondering, could you please let me know what is wrong in the following code: case class X(vv:String) val sample = new X(A) implicit val formats = net.liftweb.json.DefaultFormats import net.liftweb.json.JsonAST._ import net.liftweb.json.Extraction._ import net.liftweb.json.Printer._ def from(in:String):X=net.liftweb.json.Serialization.read[X](in) def to(in:X):String=compact(render(decompose(in))) val sample2=from(to(sample)) sample2 must_== sample I am getting java.util.NoSuchElementException: key not found: $outer Thanks, -A -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
[Lift] Re: serializing and deserializing a json object through Lift-JSON
Hi Ali, I added a ticket for this: http://www.assembla.com/spaces/liftweb/tickets/352-do-not-serialize-the-internal-state-of-a-case-class-(json) Meanwhile, you can cleanup the serialized JSON for instance by using 'remove' function. Something like: val cleanJson = decompose(x) remove { case JField(n, _) if n.contains('$') = true case _ = false } compact(render(cleanJson)) Cheers Joni On Feb 17, 1:45 pm, Ali saleh...@gmail.com wrote: Hi, I just updated to the latest lift-json snapshot and tried to serialize one of my case classes: The output starts with: { bitmap$0:0, sell_exp:null, buy_exp:null, x$3:null, sell_exp_str:null, buy_exp_str:null, x$2:null, sell_vars:null, buy_vars:null, x$1:null, For your information, things like buy_exp, buy_vars,... are declared as lazy val inside the body of the case class. I have two questions: - Is it possible to configure lift-json so It would not serialize internal variables ? case class X(a:Int) {lazy val y = a} - Is it possible to generate a clean json output without x$0 or bitmap $0,... entries ? Thanks, -A On Feb 14, 5:32 pm, Joni Freeman freeman.j...@gmail.com wrote: Hi, I just added Array support and fixed the bug 341. It is now waiting on review board for others to comment. You can checkout branch 'joni_issue_341' if you want to try it immediately. This test case now passes (Please note the verbose assertions in second test case. Those are needed because scala.Array's equals is reference comparison, Array(1, 2) == Array(1, 2) - false): http://github.com/dpp/liftweb/blob/joni_issue_341/framework/lift-base... Cheers Joni On Feb 11, 12:09 pm, Ali saleh...@gmail.com wrote: Thanks guys, Actually my problem is still there, It looks like lift-jsondoesn't support scala-arrays. case class Plan( leftOperand:Option[Action], operator:Option[String], rightOperand:Option[Action]) case class Game(buy:Map[String,Plan]) case class Action( functionName:String, symbol:String, inParams: Array[Number] , subOperand : Option[Action]) val game = new Game(Map(a-new Plan(Some(new Action(f1,s,Array(),None)),Some(A),Some(new Action(f1,s,Array(0,1,2),None) implicit val format = Serialization.formats(ShortTypeHints(List(classOf[Plan], classOf[Action], classOf[Game]))) println(Serialization.write(game)) The output is: {jsonClass:Game,buy:{a:{jsonClass:Plan,rightOperand: {jsonClass:Action,symbol:s,functionName:f1},operator:A,leftOperand: {jsonClass:Action,symbol:s,functionName:f1 which is not correct (missing the inParams field from the action class). I appreciate your comment, Cheers, -A On Feb 11, 8:44 am, Joni Freeman freeman.j...@gmail.com wrote: Hi, Type hints should not be needed in this case since the Map is not used in a polymorphic way. But the work-around Justin showed should work. Actually it seems that it is enough to put type info just to Action to make serialization work: implicit val format = Serialization.formats(ShortTypeHints(List(classOf[Action])) Anyway, I added a ticket for this defect:http://www.assembla.com/spaces/liftweb/tickets/341-Type-hints-are-nee... Cheers Joni On Feb 10, 7:49 pm, Justin Reardon justin.rear...@gmail.com wrote: Sometimes the serialization code needs a helping hand, using: implicit val format = Serialization.formats(ShortTypeHints(List(classOf[Plan], classOf[Action], classOf[Game]))) instead of the defaults makes it work here. Cheers, Justin Reardon On 2010-02-10, at 11:42 , Ali wrote: Dear All, I am wondering would you please tell me how can I uselift-json(2.0 snapshots) to serialize and deserialize the following scala case classes. case class Plan( plan:Option[Action] ) case class Game( game:Map[String,Plan]) case class Action(id:Int, subAction : Option[Action]) val game = new Game(Map(a-new Plan(new Some(new Action(1,None) implicit val formats = net.liftweb.json.DefaultFormats game must beEqualTo( Serialization.read[Game] (Serialization.write(game))) Test fails. Cheers, -A -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group athttp://groups.google.com/group/liftweb?hl=en. -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more
[Lift] Re: serializing and deserializing a json object through Lift-JSON
Fix is in master now. Should be in next snapshot build too. Cheers Joni On Feb 17, 3:27 pm, Ali saleh...@gmail.com wrote: Thank you :) -A On Feb 17, 1:23 pm, Joni Freeman freeman.j...@gmail.com wrote: Hi Ali, I added a ticket for this:http://www.assembla.com/spaces/liftweb/tickets/352-do-not-serialize-t...) Meanwhile, you can cleanup the serialized JSON for instance by using 'remove' function. Something like: val cleanJson = decompose(x) remove { case JField(n, _) if n.contains('$') = true case _ = false} compact(render(cleanJson)) Cheers Joni On Feb 17, 1:45 pm, Ali saleh...@gmail.com wrote: Hi, I just updated to the latest lift-json snapshot and tried to serialize one of my case classes: The output starts with: { bitmap$0:0, sell_exp:null, buy_exp:null, x$3:null, sell_exp_str:null, buy_exp_str:null, x$2:null, sell_vars:null, buy_vars:null, x$1:null, For your information, things like buy_exp, buy_vars,... are declared as lazy val inside the body of the case class. I have two questions: - Is it possible to configure lift-json so It would not serialize internal variables ? case class X(a:Int) {lazy val y = a} - Is it possible to generate a clean json output without x$0 or bitmap $0,... entries ? Thanks, -A On Feb 14, 5:32 pm, Joni Freeman freeman.j...@gmail.com wrote: Hi, I just added Array support and fixed the bug 341. It is now waiting on review board for others to comment. You can checkout branch 'joni_issue_341' if you want to try it immediately. This test case now passes (Please note the verbose assertions in second test case. Those are needed because scala.Array's equals is reference comparison, Array(1, 2) == Array(1, 2) - false): http://github.com/dpp/liftweb/blob/joni_issue_341/framework/lift-base... Cheers Joni On Feb 11, 12:09 pm, Ali saleh...@gmail.com wrote: Thanks guys, Actually my problem is still there, It looks like lift-jsondoesn't support scala-arrays. case class Plan( leftOperand:Option[Action], operator:Option[String], rightOperand:Option[Action]) case class Game(buy:Map[String,Plan]) case class Action( functionName:String, symbol:String, inParams: Array[Number] , subOperand : Option[Action]) val game = new Game(Map(a-new Plan(Some(new Action(f1,s,Array(),None)),Some(A),Some(new Action(f1,s,Array(0,1,2),None) implicit val format = Serialization.formats(ShortTypeHints(List(classOf[Plan], classOf[Action], classOf[Game]))) println(Serialization.write(game)) The output is: {jsonClass:Game,buy:{a:{jsonClass:Plan,rightOperand: {jsonClass:Action,symbol:s,functionName:f1},operator:A,leftOperand: {jsonClass:Action,symbol:s,functionName:f1 which is not correct (missing the inParams field from the action class). I appreciate your comment, Cheers, -A On Feb 11, 8:44 am, Joni Freeman freeman.j...@gmail.com wrote: Hi, Type hints should not be needed in this case since the Map is not used in a polymorphic way. But the work-around Justin showed should work. Actually it seems that it is enough to put type info just to Action to make serialization work: implicit val format = Serialization.formats(ShortTypeHints(List(classOf[Action])) Anyway, I added a ticket for this defect:http://www.assembla.com/spaces/liftweb/tickets/341-Type-hints-are-nee... Cheers Joni On Feb 10, 7:49 pm, Justin Reardon justin.rear...@gmail.com wrote: Sometimes the serialization code needs a helping hand, using: implicit val format = Serialization.formats(ShortTypeHints(List(classOf[Plan], classOf[Action], classOf[Game]))) instead of the defaults makes it work here. Cheers, Justin Reardon On 2010-02-10, at 11:42 , Ali wrote: Dear All, I am wondering would you please tell me how can I uselift-json(2.0 snapshots) to serialize and deserialize the following scala case classes. case class Plan( plan:Option[Action] ) case class Game( game:Map[String,Plan]) case class Action(id:Int, subAction : Option[Action]) val game = new Game(Map(a-new Plan(new Some(new Action(1,None) implicit val formats = net.liftweb.json.DefaultFormats game must beEqualTo( Serialization.read[Game] (Serialization.write(game))) Test fails. Cheers, -A -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from
[Lift] Re: serializing and deserializing a json object through Lift-JSON
Hi, I just added Array support and fixed the bug 341. It is now waiting on review board for others to comment. You can checkout branch 'joni_issue_341' if you want to try it immediately. This test case now passes (Please note the verbose assertions in second test case. Those are needed because scala.Array's equals is reference comparison, Array(1, 2) == Array(1, 2) - false): http://github.com/dpp/liftweb/blob/joni_issue_341/framework/lift-base/lift-json/src/test/scala/net/liftweb/json/SerializationBugs.scala Cheers Joni On Feb 11, 12:09 pm, Ali saleh...@gmail.com wrote: Thanks guys, Actually my problem is still there, It looks like lift-jsondoesn't support scala-arrays. case class Plan( leftOperand:Option[Action], operator:Option[String], rightOperand:Option[Action]) case class Game(buy:Map[String,Plan]) case class Action( functionName:String, symbol:String, inParams: Array[Number] , subOperand : Option[Action]) val game = new Game(Map(a-new Plan(Some(new Action(f1,s,Array(),None)),Some(A),Some(new Action(f1,s,Array(0,1,2),None) implicit val format = Serialization.formats(ShortTypeHints(List(classOf[Plan], classOf[Action], classOf[Game]))) println(Serialization.write(game)) The output is: {jsonClass:Game,buy:{a:{jsonClass:Plan,rightOperand: {jsonClass:Action,symbol:s,functionName:f1},operator:A,leftOperand: {jsonClass:Action,symbol:s,functionName:f1 which is not correct (missing the inParams field from the action class). I appreciate your comment, Cheers, -A On Feb 11, 8:44 am, Joni Freeman freeman.j...@gmail.com wrote: Hi, Type hints should not be needed in this case since the Map is not used in a polymorphic way. But the work-around Justin showed should work. Actually it seems that it is enough to put type info just to Action to make serialization work: implicit val format = Serialization.formats(ShortTypeHints(List(classOf[Action])) Anyway, I added a ticket for this defect:http://www.assembla.com/spaces/liftweb/tickets/341-Type-hints-are-nee... Cheers Joni On Feb 10, 7:49 pm, Justin Reardon justin.rear...@gmail.com wrote: Sometimes the serialization code needs a helping hand, using: implicit val format = Serialization.formats(ShortTypeHints(List(classOf[Plan], classOf[Action], classOf[Game]))) instead of the defaults makes it work here. Cheers, Justin Reardon On 2010-02-10, at 11:42 , Ali wrote: Dear All, I am wondering would you please tell me how can I use lift-json(2.0 snapshots) to serialize and deserialize the following scala case classes. case class Plan( plan:Option[Action] ) case class Game( game:Map[String,Plan]) case class Action(id:Int, subAction : Option[Action]) val game = new Game(Map(a-new Plan(new Some(new Action(1,None) implicit val formats = net.liftweb.json.DefaultFormats game must beEqualTo( Serialization.read[Game] (Serialization.write(game))) Test fails. Cheers, -A -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group athttp://groups.google.com/group/liftweb?hl=en. -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
[Lift] Re: Unclear on how to decompose a case class into JSON and then reconstitute
Hi, Unfortunately paranamer does not work with scala REPL. You need to put LastTimestamp to .scala file, compile it and then add it to the CLASSPATH. Hopefully Scala will get good reflection API some day. The we can remove dependency to paranamer (which is needed to query names of case class constructor parameters). Cheers Joni On Feb 12, 7:41 pm, Aaron Valade a...@alum.mit.edu wrote: Alright, I've got an easy one! I'm just starting to play around with lift-json and I'm having some trouble with a relatively easy case. I'm just trying to change a case class into a JSON value and then parse that back into a case class. Here's my code: import net.liftweb.json._ import JsonAST._ import JsonDSL._ import JsonParser._ import Extraction._ implicit val formats = DefaultFormats case class LastTimestamp(val localTime: Long, val globalTime: Long) val timestamps = LastTimestamp(new java.util.Date().getTime, new java.util.Date().getTime) val json = compact(render(decompose(timestamps))) parse(json).extract[LastTimestamp] == timestamps This code throws an error: com.thoughtworks.paranamer.ParameterNamesNotFoundException: Unable to get class bytes at com.thoughtworks.paranamer.BytecodeReadingParanamer.lookupParameterNames(BytecodeReadingParanamer.java:97) at com.thoughtworks.paranamer.CachingParanamer.lookupParameterNames(CachingParanamer.java:72) at com.thoughtworks.paranamer.CachingParanamer.lookupParameterNames(CachingParanamer.java:64) ... I'm using 2.0-SNAPSHOT. Thanks in advance for setting me straight! - Aaron -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
[Lift] Re: serializing and deserializing a json object through Lift-JSON
Hi, Yes, that's true. Arrays are not yet supported. Just Option, List and Map. Adding array support (which should be trivial) is on TODO list though. Cheers Joni On Feb 11, 12:09 pm, Ali saleh...@gmail.com wrote: Thanks guys, Actually my problem is still there, It looks like lift- json doesn't support scala-arrays. case class Plan( leftOperand:Option[Action], operator:Option[String], rightOperand:Option[Action]) case class Game(buy:Map[String,Plan]) case class Action( functionName:String, symbol:String, inParams: Array[Number] , subOperand : Option[Action]) val game = new Game(Map(a-new Plan(Some(new Action(f1,s,Array(),None)),Some(A),Some(new Action(f1,s,Array(0,1,2),None) implicit val format = Serialization.formats(ShortTypeHints(List(classOf[Plan], classOf[Action], classOf[Game]))) println(Serialization.write(game)) The output is: {jsonClass:Game,buy:{a:{jsonClass:Plan,rightOperand: {jsonClass:Action,symbol:s,functionName:f1},operator:A,leftOperand: {jsonClass:Action,symbol:s,functionName:f1 which is not correct (missing the inParams field from the action class). I appreciate your comment, Cheers, -A On Feb 11, 8:44 am, Joni Freeman freeman.j...@gmail.com wrote: Hi, Type hints should not be needed in this case since the Map is not used in a polymorphic way. But the work-around Justin showed should work. Actually it seems that it is enough to put type info just to Action to make serialization work: implicit val format = Serialization.formats(ShortTypeHints(List(classOf[Action])) Anyway, I added a ticket for this defect:http://www.assembla.com/spaces/liftweb/tickets/341-Type-hints-are-nee... Cheers Joni On Feb 10, 7:49 pm, Justin Reardon justin.rear...@gmail.com wrote: Sometimes the serialization code needs a helping hand, using: implicit val format = Serialization.formats(ShortTypeHints(List(classOf[Plan], classOf[Action], classOf[Game]))) instead of the defaults makes it work here. Cheers, Justin Reardon On 2010-02-10, at 11:42 , Ali wrote: Dear All, I am wondering would you please tell me how can I use lift-json(2.0 snapshots) to serialize and deserialize the following scala case classes. case class Plan( plan:Option[Action] ) case class Game( game:Map[String,Plan]) case class Action(id:Int, subAction : Option[Action]) val game = new Game(Map(a-new Plan(new Some(new Action(1,None) implicit val formats = net.liftweb.json.DefaultFormats game must beEqualTo( Serialization.read[Game] (Serialization.write(game))) Test fails. Cheers, -A -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group athttp://groups.google.com/group/liftweb?hl=en. -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
[Lift] Re: Parsed JSON values do not match with class constructor
Hi, I believe this bug is already fixed in trunk. If I'm right, the problem was missing conversion from JInt to float. You could fix it by changing these values passMarkApplied:0,thresholdApplied:0 to passMarkApplied:0.0,thresholdApplied:0.0 But it would be great if you have time to test with latest snapshot. It worked for me at least. Cheers Joni On Feb 11, 6:11 pm, GA my_li...@me.com wrote: Hello guys, I am having a very strange error parsing JSON messages. Everything was working perfect until I introduce a new array in the message. It supposed to be a very small change, but the system seems to be parsing java data types instead of scala data types. This is the error message: net.liftweb.json.MappingException: Parsed JSON values do not match with class constructor args=129567,248,1,1,0,0, String arg types=java.lang.Long,java.lang.Long,java.lang.Long,java.lang.Long,scala.BigInt,scala.BigInt,java.lang.String constructor=public com.tribes.ga.api.FeedAPI$FilterLogging$2(long,long,long,long,float,float,java.lang.String) I do not know how to solve this. There is another array in the same structure that works just fine. This is the JSON message coming into the API: {lastSync:Thursday, February11,2010, tribeId:1, filterLogging:[{passMarkApplied:0,thresholdApplied:0,entryId:129567,evaluationDescription:String,objectFiltered:1,filterApplied:1,sourceId:248}], history:7, deviceId:1036, source:248, showNews:true, userId:1049, syncFlag:false, showNewsChanged:false, updatedFeeds:[]} The error is with the array filter. I am parsing it with the following code (this is an extraction of the entire definition): case class FilterLogging(entryId: Long, sourceId: Long, objectFiltered: Long, filterApplied: Long, passMarkApplied: Float, thresholdApplied: Float, evaluationDescription: String ) case class UpdatedSource(userId: Long, deviceId: Long, tribeId: Long, syncFlag: Boolean, lastSync: String, history: Int, source: Long, updatedFeeds: List[UpdatedFeeds], filterLogging: List[FilterLogging] ) val json = parse(req.body.map(bytes = new String(bytes, UTF-8)) openOr ) val request: UpdatedSource = json.extract[UpdatedSource] Any ideas? Thanks in advance, GA -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
[Lift] Re: Parsed JSON values do not match with class constructor
Yes, it is fixed in 2.0-M2. Cheers Joni On Feb 11, 6:54 pm, GA my_li...@me.com wrote: That's exactly what I've just found out. :-) As a workaround I am forcing the client app to send 0.0. are you saying that the bug is fixed in Lift 2.0-M2? Thanks for the answer, cheers, GA On Feb 11, 2010, at 5:42 PM, Joni Freeman wrote: Hi, I believe this bug is already fixed in trunk. If I'm right, the problem was missing conversion from JInt to float. You could fix it by changing these values passMarkApplied:0,thresholdApplied:0 to passMarkApplied:0.0,thresholdApplied:0.0 But it would be great if you have time to test with latest snapshot. It worked for me at least. Cheers Joni On Feb 11, 6:11 pm, GA my_li...@me.com wrote: Hello guys, I am having a very strange error parsing JSON messages. Everything was working perfect until I introduce a new array in the message. It supposed to be a very small change, but the system seems to be parsing java data types instead of scala data types. This is the error message: net.liftweb.json.MappingException: Parsed JSON values do not match with class constructor args=129567,248,1,1,0,0, String arg types=java.lang.Long,java.lang.Long,java.lang.Long,java.lang.Long,scala.BigInt,scala.BigInt,java.lang.String constructor=public com.tribes.ga.api.FeedAPI$FilterLogging$2(long,long,long,long,float,float,java.lang.String) I do not know how to solve this. There is another array in the same structure that works just fine. This is the JSON message coming into the API: {lastSync:Thursday, February11,2010, tribeId:1, filterLogging:[{passMarkApplied:0,thresholdApplied:0,entryId:129567,evaluationDescription:String,objectFiltered:1,filterApplied:1,sourceId:248}], history:7, deviceId:1036, source:248, showNews:true, userId:1049, syncFlag:false, showNewsChanged:false, updatedFeeds:[]} The error is with the array filter. I am parsing it with the following code (this is an extraction of the entire definition): case class FilterLogging(entryId: Long, sourceId: Long, objectFiltered: Long, filterApplied: Long, passMarkApplied: Float, thresholdApplied: Float, evaluationDescription: String ) case class UpdatedSource(userId: Long, deviceId: Long, tribeId: Long, syncFlag: Boolean, lastSync: String, history: Int, source: Long, updatedFeeds: List[UpdatedFeeds], filterLogging: List[FilterLogging] ) val json = parse(req.body.map(bytes = new String(bytes, UTF-8)) openOr ) val request: UpdatedSource = json.extract[UpdatedSource] Any ideas? Thanks in advance, GA -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group athttp://groups.google.com/group/liftweb?hl=en. -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
[Lift] Re: Encoding raw HTML into single JSON element
Mike, Here's one idea. Convert the XML to JSON and the fix the markup field. Something like: toJson(xml) map { case JField(markup, _) = JField(markup, JString((xml \\ markup).toString)) case x = x } Does that work for you? Cheers Joni On Feb 11, 8:51 pm, Mike mike.c.single...@gmail.com wrote: Looking for some advise about encoding raw HTML to JSON. Here as some sample XML similar to what we are using: id846/id nameMike/name markup div h1testing/h1 /div /markup When converting this XML to JSON I would like the markup element and all of it's children to be returned as a big string. For example: {id: 846, name: Mike, markup, divh1testing/h1/div} Right now it always tries to parse the children, resulting in something similar to: {id: 846, name: Mike, markup:{div:{h1:testing}} Any insights? -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
[Lift] Re: serializing and deserializing a json object through Lift-JSON
Hi, Type hints should not be needed in this case since the Map is not used in a polymorphic way. But the work-around Justin showed should work. Actually it seems that it is enough to put type info just to Action to make serialization work: implicit val format = Serialization.formats(ShortTypeHints(List(classOf[Action])) Anyway, I added a ticket for this defect: http://www.assembla.com/spaces/liftweb/tickets/341-Type-hints-are-needed-in-JSON-serializization-for-non-polymorphic-Map- Cheers Joni On Feb 10, 7:49 pm, Justin Reardon justin.rear...@gmail.com wrote: Sometimes the serialization code needs a helping hand, using: implicit val format = Serialization.formats(ShortTypeHints(List(classOf[Plan], classOf[Action], classOf[Game]))) instead of the defaults makes it work here. Cheers, Justin Reardon On 2010-02-10, at 11:42 , Ali wrote: Dear All, I am wondering would you please tell me how can I use lift-json(2.0 snapshots) to serialize and deserialize the following scala case classes. case class Plan( plan:Option[Action] ) case class Game( game:Map[String,Plan]) case class Action(id:Int, subAction : Option[Action]) val game = new Game(Map(a-new Plan(new Some(new Action(1,None) implicit val formats = net.liftweb.json.DefaultFormats game must beEqualTo( Serialization.read[Game] (Serialization.write(game))) Test fails. Cheers, -A -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group athttp://groups.google.com/group/liftweb?hl=en. -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
[Lift] Re: **Important** Code Slush
Done. Thanks Joni On Feb 8, 7:46 pm, David Pollak feeder.of.the.be...@gmail.com wrote: On Mon, Feb 8, 2010 at 9:45 AM, Joni Freeman freeman.j...@gmail.com wrote: David, This bug fix is waiting on RB. Don't know how critical it is but the fix looks trivial. Reviewed. Merge it on it please. http://reviewboard.liftweb.net/r/203/ Cheers Joni On Feb 8, 7:28 pm, David Pollak feeder.of.the.be...@gmail.com wrote: Folks, We're planning to do 2.0-M2 release on Wednesday. We're officially on code slush to give 4[], Udorse and other production sites that run on the milestones to test the existing code. That means no code gets committed to master unless it's a bug fix for something that's reported against the currently slushed code or if there's another *very good* reason. Harry, Jonathan, production folks... what do you need for M2? Thanks, David -- Lift, the simply functional web frameworkhttp://liftweb.net Beginning Scalahttp://www.apress.com/book/view/1430219890 Follow me:http://twitter.com/dpp Surf the harmonics -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.comliftweb%2bunsubscr...@googlegroups.com . For more options, visit this group at http://groups.google.com/group/liftweb?hl=en. -- Lift, the simply functional web frameworkhttp://liftweb.net Beginning Scalahttp://www.apress.com/book/view/1430219890 Follow me:http://twitter.com/dpp Surf the harmonics -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
[Lift] Re: lift-json serialization
Hi, Serialization feature is actually a very thin layer on top of decompose and extract functions. So, one way to accomplish that is to use directly those functions and map the field names. So, instead of this: write(x, out) Try this: val json = decompose(x) map { case JField(firstname, x) = JField(fn, x) case JField(lastname, x) = JField(ln, x) case x = x } compact(render(json), out) And instead of this: read[Users](x) Try this: parse(x).extract[Users] map { case JField(fn, x) = JField(firstname, x) case JField(ln, x) = JField(lastname, x) case x = x } Would that solve your issue? Cheers Joni On Feb 9, 6:27 am, harryh har...@gmail.com wrote: A feature request. Right now I might have a case class like so: case class User(firstname: String, lastname: String) which serializes to something like: { firstname : Harry, lastname : Heymann } but I happen to be serializing a lot of People and I hate to use 17 bytes per item for the field names. I'd really prefer to only use 4: { fn : Harry, ln : Heymann } It seems to me that through clever use of an implicit parameter I ought to be pass in a Map of field name - shortened names. Thoughts? -harryh -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
[Lift] Re: lift-Json doesn't appear to be correctly handling attributes.
Thanks, The fix is on review board now. Should be in master pretty soon. Note, I made two changes to the test case you provided. The expected result of example1 is: {word:content,self:http://localhost:8080/word/ example,term:example,available:true} The transformation converts XML attributes to fields in resulting JSON object. The reason for this rule is that it keeps transformation more stable. That is, these both will generate structurally equivalent JSON: wordfoo/word - {word:foo} word attr=barfoo/word - {word:foo,attr:bar} The expected result of example2 is: {word:null,self:http://localhost:8080/word/ example,term:example,available:true} Field word is null since there's no content: word .../word Cheers Joni On Feb 3, 11:31 pm, Jonathan Ferguson j...@spiralarm.com wrote: Thanks Joni, I've opened a ticket http://github.com/dpp/liftweb/issues/issue/323. Cheers Jono On 3 February 2010 17:46, Joni Freeman freeman.j...@gmail.com wrote: Hi Jonathan, Yes, definitely a bug. Could you please open a ticket (http:// github.com/dpp/liftweb/issues) and I will take a look at it. And thanks for the test case! Cheers Joni On Feb 3, 3:41 am, Jonathan Ferguson j...@spiralarm.com wrote: When converting XML to Json attributes are being lost, given the below XML document, we would expect {word:{word:content,self:http://localhost:8080/word/example ,term:example,available:true}} where as we get {word:content} example XML: word term=example self=http://localhost:8080/word/example; available=truecontent/word This is been tested on M1 and trunk. Thanks in advance. To repeat // From the command line, adjust paths as needed $scala -cp /Users/jono/.m2/repository/com/thoughtworks/paranamer/paranamer/2.0/paranamer-2.0.jar:/Users/jono/.m2/repository/net/liftweb/lift-json/2.0-SNAPSHOT/lift-json-2.0-SNAPSHOT.jar import scala.xml._ import net.liftweb.json.JsonAST._ import net.liftweb.json.Printer import net.liftweb.json.Xml val example1 = word term=example self= http://localhost:8080/word/example; available=truecontent/word val expected1 = {word:{word:content,self: http://localhost:8080/word/example ,term:example,available:true}} val got1 = Printer.compact(render(Xml.toJson(example1))) val example2 = word term=example self= http://localhost:8080/word/example; available=true/word val expected2 = {word:{word:content,self: http://localhost:8080/word/example ,term:example,available:true}} val got2 = Printer.compact(render(Xml.toJson(example2))) // Add to src/test/scala/net/liftweb/json/XmlBugs.scala Jono's XML with attributes parses correctly in { val example1 = word term=example self= http://localhost:8080/word/example; available=truecontent/word val expected1 = {word:{word:content,self: http://localhost:8080/word/example ,term:example,available:true}} val example2 = word term=example self= http://localhost:8080/word/example; available=true/word val expected2 = {word:{word:content,self: http://localhost:8080/word/example ,term:example,available:true}} Printer.compact(render(toJson(example1))) mustEqual expected1 Printer.compact(render(toJson(example2))) mustEqual expected2 } Here is what I get when I run the example provided. $scala -cp /Users/jono/.m2/repository/com/thoughtworks/paranamer/paranamer/2.0/paranamer-2.0.jar:/Users/jono/.m2/repository/net/liftweb/lift-json/2.0-SNAPSHOT/lift-json-2.0-SNAPSHOT.jar Welcome to Scala version 2.7.7.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_17). Type in expressions to have them evaluated. Type :help for more information. scala import scala.xml._ import scala.xml._ scala import net.liftweb.json.JsonAST._ import net.liftweb.json.JsonAST._ scala import net.liftweb.json.Printer import net.liftweb.json.Printer scala import net.liftweb.json.Xml import net.liftweb.json.Xml scala scala val example1 = word term=example self= http://localhost:8080/word/example; available=truecontent/word example1: scala.xml.Elem = word self= http://localhost:8080/word/example; term=example available=truecontent/word scala val expected1 = {word:{word:content,self: http://localhost:8080/word/example ,term:example,available:true}} expected1: java.lang.String = {word:{word:content,self: http://localhost:8080/word/example,term:example,available:true}} scala val got1 = Printer.compact(render(Xml.toJson(example1))) got1: String = {word:content} scala Jono P.S I thought I had a fix, but it broke one of HarryH's tests. scala scala val example2 = word term=example self= http://localhost:8080/word/example; available=true/word example2: scala.xml.Elem = word self= http://localhost:8080/word/example; term=example available=true/word scala val expected2 = {word:{word:content,self: http://localhost:8080/word/example
[Lift] Re: (ISSUE) How to use the sbt with lift project ?
Hi, A colleague of mine did a skeleton project for sbt. It may give you some hints how to proceed. http://github.com/vvilhonen/SBT-Lift-Skeleton Cheers Joni On Jan 30, 8:14 am, Neil.Lv anim...@gmail.com wrote: Hi all, How to use the sbt with lift project ? I try to use the sbt and get this errors, Does anybody know what's wrong with it ? Maybe i missing something else ? Here is the log: # I create this file like this in the build directory. G:\project\test\project\build\TestProject.scala import sbt._ class TestProject(info: ProjectInfo) extends DefaultWebProject(info) { override lazy val jetty = org.mortbay.jetty % jetty % 6.1.22 % test-default } # G:\project\testsbt G:\project\testset SCRIPT_DIR=G:\cygwin\home\ G:\project\testjava -Xmx64M -jar G:\cygwin\home\sbt- launcher-0.5.6.jar Project does not exist, create new project? (y/N/s) : y Name: test Organization []: Version [1.0]: Scala version [2.7.7]: sbt version [0.5.6]: :: retrieving :: sbt#boot confs: [default] 2 artifacts copied, 0 already retrieved (9911kB/625ms) :: retrieving :: sbt#boot confs: [default] 3 artifacts copied, 0 already retrieved (3409kB/547ms) [success] Successfully initialized directory structure. [info] Building project test 1.0 using sbt.DefaultProject [info] with sbt 0.5.6 and Scala 2.7.7 [info] No actions specified, interactive session started. Execute 'help' for more information. 1: Get this error when use sbt update command G:\project\testsbt update G:\project\testset SCRIPT_DIR=G:\cygwin\home\ G:\project\testjava -Xmx64M -jar G:\cygwin\home\sbt- launcher-0.5.6.jar update [error] G:\project\test\project\build\TestProject.scala:5: error overriding lazy value jetty in class BasicWebScalaP roject of type TestProject.this.Task; [error] value jetty needs `override' modifier [error] val jetty = org.mortbay.jetty % jetty % 6.1.22 % test- default - 2: When I add the override in the definition, and get this error. [error] G:\project\test\project\build\TestProject.scala:5: error overriding lazy value jetty in class BasicWebScalaP roject of type TestProject.this.Task; [error] value jetty must be declared lazy to override a concrete lazy value [error] override val jetty = org.mortbay.jetty % jetty % 6.1.22 % test-default [error] ^ [error] one error found Compilation unsuccessful. - 3: Add lazy into the statement and get this error. [error] G:\project\test\project\build\TestProject.scala:5: error overriding lazy value jetty in class BasicWebScalaP roject of type TestProject.this.Task; [error] lazy value jetty has incompatible type sbt.ModuleID [error] override lazy val jetty = org.mortbay.jetty % jetty % 6.1.22 % test-default # Thanks for any help! Cheers, Neil -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
[Lift] Re: Parcing Json
Ok, thanks for clarification. Unfortunately my knowledge about mapper is very limited (I've previously used ScalaQuery for db persistence). Maybe someone else can answer the question better, the question being: What is the easiest way to store instances of Observations into database using mapper. case class Observation(notice: List[Notice], header: List[Header], data: List[Data]) Notice, Header and Data are simple case classes having just primitive fields. Cheers Joni On 11 tammi, 10:36, Randinn rand...@gmail.com wrote: Sorry for the confusion Observation is a table actually, I meant to write mapper. So what we're doing is calling up the json file, making it a string, putting it through the parcer and inserting it into the table. On Jan 11, 5:49 pm, Joni Freeman freeman.j...@gmail.com wrote: Hi, I'm sorry but I'm not totally sure what you are trying to accomplish. What would be the key in that map and what would be its values? Cheers Joni On 11 tammi, 03:14, Randinn rand...@gmail.com wrote: I should explain what we are planning, the idea is to get the json file into a string, parse it and save the caught information into a Observation map. On Jan 11, 11:23 am, Randinn rand...@gmail.com wrote: Forgive my ignorance but I was wondering why (json \ observations).extract[Observation], is it to save as a flat file? On Jan 4, 7:13 am, Randinn rand...@gmail.com wrote: I tried some of the changes you made but not all of them, and (json\ observations).extract[Observation], I had no idea about that one. Thank you very much for your help, it is appreciated. On Jan 4, 1:00 am, Joni Freeman freeman.j...@gmail.com wrote: Google Groups does not shine in formatting code snippets. Here's nicer version: http://paste.pocoo.org/show/161578/ Cheers Joni On 3 tammi, 12:20, Joni Freeman freeman.j...@gmail.com wrote: Hi, That's almost correct. I did following changes after looking intoJSON content. 1. 'notice' and 'header' areJSONarrays just like 'data'. Therefore: case class Observation(notice: List[Notice], header: List[Header], data: List[Data]) 2. There's optional data inJSON(some datapoints are nulls and Scala Int or Double can't take null values). This can be fixed by extracting into Option. 3. The extracted Observation is inJSONfield 'observations'. Therefore: (json\ observations).extract[Observation] Your error stack trace suggests that you have an old version of lift- json. Please upgrade to M8, there was a critical bug in case class extraction in older versions. Full example which works for me: implicit val formats = net.liftweb.json.DefaultFormats case class Notice(copyright: String, copyright_url: String, disclaimer_url: String) case class Header(refresh_message: String, ID: String, main_ID: String, name: String, state_time_zone: String, time_zone: String, product_name: String, state: String) case class Data(sort_order: Int, wmo: Int, history_product: String, local_date_time: String, local_date_time_full: String, air_temp: Option [Double], dewpt: Option[Double], apparent_t: Option[Double], rel_hum: Option[Int], delta_t: Option[Double], wind_dir: String, wind_spd_kt: Option[Double], gust_kt: Option [Double], wind_spd_kmh: Option[Double], press: Option[Double], rain_trace: String) case class Observation(notice: List[Notice], header: List[Header], data: List[Data]) (json\ observations).extract[Observation] Cheers Joni On 3 tammi, 09:17, Randinn rand...@gmail.com wrote: I'm having a bit of trouble with LiftJsonparcing, I know I'm not doing it correctly but looking at the examples I cannot figure out what, anyway, here is the code in question. If someone could point me in the right direction that would be great, thanks in advance. class HelloWorld { def howdy = spanWelcome to hello-lift at {new _root_.java.util.Date}/span val http = new Http val bos = new ByteArrayOutputStream val myRequest = new Request(http://www.bom.gov.au/fwo/IDV60901/ IDV60901.94868.json) val rawdata = http(myRequest bos) val bs = bos.toString val db = :/(www.bom.gov.au) valjson= parse(bs) implicit val formats = net.liftweb.json.DefaultFormats case class Notice(copyright: String, copyright_url: String, disclaimer_url: String) case class Header(refresh_message: String, ID: String, main_ID: String, name: String, state_time_zone: String
[Lift] Re: Parcing Json
Tim, ScalaQuery is a great DSL to interface relational database and to construct type safe SQL queries. I find that kind of approach often preferable compared to full blown ORMs (like Hibernate etc.) since it gives full control over SQL queries and does not impose any constraints on object model. At the moment it is a bit difficult to use ScalaQuery with Lift since latest versions of ScalaQuery requires Scala 2.8. But once Lift is fully on 2.8 there should be no problems at all in using it in Lift app. ScalaQuery is still work in progress and there hasn't been any official release as far as I know, the documentation is also severely lacking. Cheers Joni On 11 tammi, 13:32, Timothy Perrett timo...@getintheloop.eu wrote: Hey Joni, What did you think of ScalaQuery btw? Have you used it inside a lift app? Cheers, Tim On 11 Jan 2010, at 11:07, Joni Freeman wrote: Ok, thanks for clarification. Unfortunately my knowledge about mapper is very limited (I've previously used ScalaQuery for db persistence). Maybe someone else can answer the question better, the question being: What is the easiest way to store instances of Observations into database using mapper. case class Observation(notice: List[Notice], header: List[Header], data: List[Data]) Notice, Header and Data are simple case classes having just primitive fields. Cheers Joni On 11 tammi, 10:36, Randinn rand...@gmail.com wrote: Sorry for the confusion Observation is a table actually, I meant to write mapper. So what we're doing is calling up thejsonfile, making it a string, putting it through the parcer and inserting it into the table. On Jan 11, 5:49 pm, Joni Freeman freeman.j...@gmail.com wrote: Hi, I'm sorry but I'm not totally sure what you are trying to accomplish. What would be the key in that map and what would be its values? Cheers Joni On 11 tammi, 03:14, Randinn rand...@gmail.com wrote: I should explain what we are planning, the idea is to get thejson file into a string, parse it and save the caught information into a Observation map. On Jan 11, 11:23 am, Randinn rand...@gmail.com wrote: Forgive my ignorance but I was wondering why (json\ observations).extract[Observation], is it to save as a flat file? On Jan 4, 7:13 am, Randinn rand...@gmail.com wrote: I tried some of the changes you made but not all of them, and (json\ observations).extract[Observation], I had no idea about that one. Thank you very much for your help, it is appreciated. On Jan 4, 1:00 am, Joni Freeman freeman.j...@gmail.com wrote: Google Groups does not shine in formatting code snippets. Here's nicer version: http://paste.pocoo.org/show/161578/ Cheers Joni On 3 tammi, 12:20, Joni Freeman freeman.j...@gmail.com wrote: Hi, That's almost correct. I did following changes after looking intoJSON content. 1. 'notice' and 'header' areJSONarrays just like 'data'. Therefore: case class Observation(notice: List[Notice], header: List[Header], data: List[Data]) 2. There's optional data inJSON(some datapoints are nulls and Scala Int or Double can't take null values). This can be fixed by extracting into Option. 3. The extracted Observation is inJSONfield 'observations'. Therefore: (json\ observations).extract[Observation] Your error stack trace suggests that you have an old version of lift- json. Please upgrade to M8, there was a critical bug in case class extraction in older versions. Full example which works for me: implicit val formats = net.liftweb.json.DefaultFormats case class Notice(copyright: String, copyright_url: String, disclaimer_url: String) case class Header(refresh_message: String, ID: String, main_ID: String, name: String, state_time_zone: String, time_zone: String, product_name: String, state: String) case class Data(sort_order: Int, wmo: Int, history_product: String, local_date_time: String, local_date_time_full: String, air_temp: Option [Double], dewpt: Option[Double], apparent_t: Option[Double], rel_hum: Option[Int], delta_t: Option[Double], wind_dir: String, wind_spd_kt: Option[Double], gust_kt: Option [Double], wind_spd_kmh: Option[Double], press: Option[Double], rain_trace: String) case class Observation(notice: List[Notice], header: List[Header], data: List[Data]) (json\ observations).extract[Observation] Cheers Joni On 3 tammi, 09:17, Randinn rand...@gmail.com wrote: I'm having a bit of trouble with LiftJsonparcing, I know I'm not doing it correctly but looking at the examples I cannot figure out what, anyway, here is the code in question. If someone could point me in the right direction that would be great, thanks in advance. class HelloWorld { def howdy = spanWelcome to hello-lift at {new _root_.java.util.Date}/span val http = new Http val bos = new ByteArrayOutputStream val
[Lift] Re: Parcing Json
Hi, I'm sorry but I'm not totally sure what you are trying to accomplish. What would be the key in that map and what would be its values? Cheers Joni On 11 tammi, 03:14, Randinn rand...@gmail.com wrote: I should explain what we are planning, the idea is to get the json file into a string, parse it and save the caught information into a Observation map. On Jan 11, 11:23 am, Randinn rand...@gmail.com wrote: Forgive my ignorance but I was wondering why (json \ observations).extract[Observation], is it to save as a flat file? On Jan 4, 7:13 am, Randinn rand...@gmail.com wrote: I tried some of the changes you made but not all of them, and (json\ observations).extract[Observation], I had no idea about that one. Thank you very much for your help, it is appreciated. On Jan 4, 1:00 am, Joni Freeman freeman.j...@gmail.com wrote: Google Groups does not shine in formatting code snippets. Here's nicer version: http://paste.pocoo.org/show/161578/ Cheers Joni On 3 tammi, 12:20, Joni Freeman freeman.j...@gmail.com wrote: Hi, That's almost correct. I did following changes after looking intoJSON content. 1. 'notice' and 'header' areJSONarrays just like 'data'. Therefore: case class Observation(notice: List[Notice], header: List[Header], data: List[Data]) 2. There's optional data inJSON(some datapoints are nulls and Scala Int or Double can't take null values). This can be fixed by extracting into Option. 3. The extracted Observation is inJSONfield 'observations'. Therefore: (json\ observations).extract[Observation] Your error stack trace suggests that you have an old version of lift- json. Please upgrade to M8, there was a critical bug in case class extraction in older versions. Full example which works for me: implicit val formats = net.liftweb.json.DefaultFormats case class Notice(copyright: String, copyright_url: String, disclaimer_url: String) case class Header(refresh_message: String, ID: String, main_ID: String, name: String, state_time_zone: String, time_zone: String, product_name: String, state: String) case class Data(sort_order: Int, wmo: Int, history_product: String, local_date_time: String, local_date_time_full: String, air_temp: Option [Double], dewpt: Option[Double], apparent_t: Option[Double], rel_hum: Option[Int], delta_t: Option[Double], wind_dir: String, wind_spd_kt: Option[Double], gust_kt: Option [Double], wind_spd_kmh: Option[Double], press: Option[Double], rain_trace: String) case class Observation(notice: List[Notice], header: List[Header], data: List[Data]) (json\ observations).extract[Observation] Cheers Joni On 3 tammi, 09:17, Randinn rand...@gmail.com wrote: I'm having a bit of trouble with LiftJsonparcing, I know I'm not doing it correctly but looking at the examples I cannot figure out what, anyway, here is the code in question. If someone could point me in the right direction that would be great, thanks in advance. class HelloWorld { def howdy = spanWelcome to hello-lift at {new _root_.java.util.Date}/span val http = new Http val bos = new ByteArrayOutputStream val myRequest = new Request(http://www.bom.gov.au/fwo/IDV60901/ IDV60901.94868.json) val rawdata = http(myRequest bos) val bs = bos.toString val db = :/(www.bom.gov.au) valjson= parse(bs) implicit val formats = net.liftweb.json.DefaultFormats case class Notice(copyright: String, copyright_url: String, disclaimer_url: String) case class Header(refresh_message: String, ID: String, main_ID: String, name: String, state_time_zone: String, time_zone: String, product_name: String, state: String) case class Data(sort_order: Int, wmo: Int, history_product: String, local_date_time: String, local_date_time_full: Int, air_temp: Double, dewpt: Double, apparent_t: Double, rel_hum: Double, delta_t: Double, wind_dir: Double, wind_spd_kt: Double, gust_kt: Double, wind_spd_kmh: Double, press: Double, rain_trace: Double) case class Observation(notice: Notice, header: Header, data: List [Data]) json.extract[Observation] -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
[Lift] Re: Parcing Json
Hi, That's almost correct. I did following changes after looking into JSON content. 1. 'notice' and 'header' are JSON arrays just like 'data'. Therefore: case class Observation(notice: List[Notice], header: List[Header], data: List[Data]) 2. There's optional data in JSON (some datapoints are nulls and Scala Int or Double can't take null values). This can be fixed by extracting into Option. 3. The extracted Observation is in JSON field 'observations'. Therefore: (json \ observations).extract[Observation] Your error stack trace suggests that you have an old version of lift- json. Please upgrade to M8, there was a critical bug in case class extraction in older versions. Full example which works for me: implicit val formats = net.liftweb.json.DefaultFormats case class Notice(copyright: String, copyright_url: String, disclaimer_url: String) case class Header(refresh_message: String, ID: String, main_ID: String, name: String, state_time_zone: String, time_zone: String, product_name: String, state: String) case class Data(sort_order: Int, wmo: Int, history_product: String, local_date_time: String, local_date_time_full: String, air_temp: Option [Double], dewpt: Option[Double], apparent_t: Option[Double], rel_hum: Option[Int], delta_t: Option[Double], wind_dir: String, wind_spd_kt: Option[Double], gust_kt: Option [Double], wind_spd_kmh: Option[Double], press: Option[Double], rain_trace: String) case class Observation(notice: List[Notice], header: List[Header], data: List[Data]) (json \ observations).extract[Observation] Cheers Joni On 3 tammi, 09:17, Randinn rand...@gmail.com wrote: I'm having a bit of trouble with Lift Json parcing, I know I'm not doing it correctly but looking at the examples I cannot figure out what, anyway, here is the code in question. If someone could point me in the right direction that would be great, thanks in advance. class HelloWorld { def howdy = spanWelcome to hello-lift at {new _root_.java.util.Date}/span val http = new Http val bos = new ByteArrayOutputStream val myRequest = new Request(http://www.bom.gov.au/fwo/IDV60901/ IDV60901.94868.json) val rawdata = http(myRequest bos) val bs = bos.toString val db = :/(www.bom.gov.au) val json = parse(bs) implicit val formats = net.liftweb.json.DefaultFormats case class Notice(copyright: String, copyright_url: String, disclaimer_url: String) case class Header(refresh_message: String, ID: String, main_ID: String, name: String, state_time_zone: String, time_zone: String, product_name: String, state: String) case class Data(sort_order: Int, wmo: Int, history_product: String, local_date_time: String, local_date_time_full: Int, air_temp: Double, dewpt: Double, apparent_t: Double, rel_hum: Double, delta_t: Double, wind_dir: Double, wind_spd_kt: Double, gust_kt: Double, wind_spd_kmh: Double, press: Double, rain_trace: Double) case class Observation(notice: Notice, header: Header, data: List [Data]) json.extract[Observation] -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
[Lift] Re: Parcing Json
Google Groups does not shine in formatting code snippets. Here's nicer version: http://paste.pocoo.org/show/161578/ Cheers Joni On 3 tammi, 12:20, Joni Freeman freeman.j...@gmail.com wrote: Hi, That's almost correct. I did following changes after looking into JSON content. 1. 'notice' and 'header' are JSON arrays just like 'data'. Therefore: case class Observation(notice: List[Notice], header: List[Header], data: List[Data]) 2. There's optional data in JSON (some datapoints are nulls and Scala Int or Double can't take null values). This can be fixed by extracting into Option. 3. The extracted Observation is in JSON field 'observations'. Therefore: (json \ observations).extract[Observation] Your error stack trace suggests that you have an old version of lift- json. Please upgrade to M8, there was a critical bug in case class extraction in older versions. Full example which works for me: implicit val formats = net.liftweb.json.DefaultFormats case class Notice(copyright: String, copyright_url: String, disclaimer_url: String) case class Header(refresh_message: String, ID: String, main_ID: String, name: String, state_time_zone: String, time_zone: String, product_name: String, state: String) case class Data(sort_order: Int, wmo: Int, history_product: String, local_date_time: String, local_date_time_full: String, air_temp: Option [Double], dewpt: Option[Double], apparent_t: Option[Double], rel_hum: Option[Int], delta_t: Option[Double], wind_dir: String, wind_spd_kt: Option[Double], gust_kt: Option [Double], wind_spd_kmh: Option[Double], press: Option[Double], rain_trace: String) case class Observation(notice: List[Notice], header: List[Header], data: List[Data]) (json \ observations).extract[Observation] Cheers Joni On 3 tammi, 09:17, Randinn rand...@gmail.com wrote: I'm having a bit of trouble with Lift Json parcing, I know I'm not doing it correctly but looking at the examples I cannot figure out what, anyway, here is the code in question. If someone could point me in the right direction that would be great, thanks in advance. class HelloWorld { def howdy = spanWelcome to hello-lift at {new _root_.java.util.Date}/span val http = new Http val bos = new ByteArrayOutputStream val myRequest = new Request(http://www.bom.gov.au/fwo/IDV60901/ IDV60901.94868.json) val rawdata = http(myRequest bos) val bs = bos.toString val db = :/(www.bom.gov.au) val json = parse(bs) implicit val formats = net.liftweb.json.DefaultFormats case class Notice(copyright: String, copyright_url: String, disclaimer_url: String) case class Header(refresh_message: String, ID: String, main_ID: String, name: String, state_time_zone: String, time_zone: String, product_name: String, state: String) case class Data(sort_order: Int, wmo: Int, history_product: String, local_date_time: String, local_date_time_full: Int, air_temp: Double, dewpt: Double, apparent_t: Double, rel_hum: Double, delta_t: Double, wind_dir: Double, wind_spd_kt: Double, gust_kt: Double, wind_spd_kmh: Double, press: Double, rain_trace: Double) case class Observation(notice: Notice, header: Header, data: List [Data]) json.extract[Observation] -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
[Lift] Re: Mapper - JObject bridge
Hi, Yes, that's a way to convert JSON AST to string and vice versa. All functions in lift-json operate on AST instances. This is lets us post- and pre-process JSON in many ways before converting it to string. See for instance functions map, merge, diff, \, etc. defined in JsonAST (scaladocs still missing but will be provided before Lift 2.0 is released). Typical conversions might for instance remove some data from JSON, convert data types, change structure of resulting JSON and so on. I usually import all needed objects and their members. After that the code becomes a bit more concise (the cast is unfortunately needed since JSON comes from the wild and can be anything): def encodeAsJsonString(in: A) = compact(render(encodeAsJson(in))) def buildFromJsonString(json: String): A = buildFromJson(parse (json).asInstanceOf[JObject]) Cheers Joni On 16 joulu, 09:03, Xuefeng Wu ben...@gmail.com wrote: Hi, I add two method to en/decode JObject/String def encodeAsJsonString(in: A): String = Printer.compact(JsonAST.render(encodeAsJson(in))) def buildFromJsonString(json: String): A = buildFromJson(JsonParser.parse(json).asInstanceOf[JsonAST.JObject]) Do there have better way? On Thu, Dec 3, 2009 at 5:15 AM, David Pollak feeder.of.the.be...@gmail.comwrote: Folks (HarryH -- this means you), I've just checked in code on the dpp_issue_213 that does Mapper - JObject bridging using the awesome lift-json library. The methods on MetaMapper: protected def encodeAsJSON_! (toEncode: A): JsonAST.JObject protected def decodeFromJSON_!(json: JsonAST.JObject): A Implement the bridge. They are protected and have a _! in their name because they are *dangerous* in that data can be exposed on the JSON object that you might not want exposed and these methods should be used with extreme caution. An example of usage can be found in the MapperSpecs: object SampleModel extends SampleModel with KeyedMetaMapper[Long, SampleModel] { def encodeAsJson(in: SampleModel): JsonAST.JObject = encodeAsJSON_!(in) def buildFromJson(json: JsonAST.JObject): SampleModel = decodeFromJSON_!(json) } class SampleModel extends KeyedMapper[Long, SampleModel] { def getSingleton = SampleModel // what's the meta server def primaryKeyField = id object id extends MappedLongIndex(this) object firstName extends MappedString(this, 32) object moose extends MappedNullableLong(this) object notNull extends MappedString(this, 32) { override def dbNotNull_? = true } def encodeAsJson(): JsonAST.JObject = SampleModel.encodeAsJson(this) } So, you can use this mechanism to serialize a Mapper object to JSON, shovel the object into memcached and then pull it out, mutate a field and save the object back to the database (although connection identifier is lost, so if you are sharding your database, this will not work). Please give it a try, give me feedback. I'll put it on review board tomorrow after any feedback and get it into Lift. Thanks, David -- Lift, the simply functional web frameworkhttp://liftweb.net Beginning Scalahttp://www.apress.com/book/view/1430219890 Follow me:http://twitter.com/dpp Surf the harmonics -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.comliftweb%2bunsubscr...@googlegroups.com . For more options, visit this group at http://groups.google.com/group/liftweb?hl=en. -- Scala中文社区: http://groups.google.com/group/scalacn -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
[Lift] Re: lift-json escaping bug
Hi, This is from JSON RFC (http://www.ietf.org/rfc/rfc4627.txt): A JSON text is a serialized object or array. I checked with another parser (http://www.jsonlint.com) and it fails too when given just JSON value: syntax error, unexpected TNUMBER, expecting '{' or '[' at line 1 So perhaps a better error message is a proper fix here? Cheers Joni On 1 joulu, 05:22, Ross Mellgren dri...@gmail.com wrote: On review board:http://reviewboard.liftweb.net/r/131/ I did run across another infelicity when writing the test -- apparently JsonParser crashes when given a scalar value, as opposed to an array or object: scala parse(\foobar\) net.liftweb.json.JsonParser$ParseException: unexpected null Near: foobar at net.liftweb.json.JsonParser$Parser.fail(JsonParser.scala:166) at net.liftweb.json.JsonParser$ValStack.peek(JsonParser.scala:153) at net.liftweb.json.JsonParser$.newValue$1(JsonParser.scala:110) at net.liftweb.json.JsonParser$.parse0(JsonParser.scala:125) at net.liftweb.json.JsonParser$.parse(JsonParser.s... I'm not sure if it should work, but even if it shouldn't support that the error case should probably give a better message. Joni/et al? -Ross On Nov 30, 2009, at 8:33 PM, harryh wrote: Done: http://github.com/dpp/liftweb/issues/#issue/214 On Nov 30, 6:33 pm, Ross Mellgren dri...@gmail.com wrote: If you file an issue on github I'll write up a patch for you tonight. -Ross On Nov 30, 2009, at 6:30 PM, harryh wrote: Yes, what Ross said. Further, taking a look at JsonParser.scala the bug appears to be on line ~202 where there are a couple of missing escape sequences: \/ as well as \f. -harryh On Nov 30, 6:20 pm, Ross Mellgren dri...@gmail.com wrote: He's double escaping so that scala's string interpretation will put a raw \ in there, so that it's an escaped forward slash (\/) to the JSON parson, as I understand it. The output should be either invalid escape or forward slash, but not backslash unless the input was \\. -Ross On Nov 30, 2009, at 6:18 PM, Peter Robinett wrote: Harry, I think you're double-escaping the slash. This works: scala import net.liftweb.json._ scala val s1 = { \id\: \America/New_York\ } s1: java.lang.String = { id: America/New_York } scala JsonParser.parse(s1) res0: net.liftweb.json.JsonAST.JValue = JObject(List(JField (id,JString (America/New_York Peter Robinett On Nov 30, 2:16 pm, harryh har...@gmail.com wrote: scala import net.liftweb.json._ scala val s2 = { \id\: \America\\/New_York\ } s2: java.lang.String = { id: America\/New_York } scala JsonParser.parse(s2) res1: net.liftweb.json.JsonAST.JValue = JObject(List(JField (id,JString (America\New_York It should be America/New_York but for some reason getting a \ instead of a / -harryh -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com . For more options, visit this group athttp://groups.google.com/group/liftweb?hl=en . -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com . For more options, visit this group athttp://groups.google.com/group/liftweb?hl=en . -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group athttp://groups.google.com/group/liftweb?hl=en. -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
[Lift] Re: lift-json question related to Lists of things
Hi, Totally agreed, this makes List extraction more robust. The change is in reviewboard now: http://reviewboard.liftweb.net/r/127/ Cheers Joni On 25 marras, 20:42, harryh har...@gmail.com wrote: consider: case class Foo(id: Int, bars: List[Bar]) case class Bar(id: Int) val foo = json.extract[Foo] The following json will cause a problem: { id: 12 } This can be fixed by changing bars to an Option[List[Bar]]. Should that really be necessary though? Can't bars just be an empty list if there are none of them? -harryh -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
[Lift] Re: Okay... part of the slow problem is javax.script
David, it's probably a broken Specs 1.6.1 which causes this. Please see this: http://github.com/robey/xrayspecs/issues/closed/#issue/1 Cheers Joni On 23 marras, 22:06, David Pollak feeder.of.the.be...@gmail.com wrote: On Mon, Nov 23, 2009 at 12:02 PM, Ross Mellgren dri...@gmail.com wrote: mvn dependency:tree Cool. Thanks! -Ross On Nov 23, 2009, at 2:55 PM, David Pollak wrote: Folks, I've narrowed down part of the slowness problem. There's a reference to javax.script:script-js that's never satisfied. How can I track down what is including this reference or alternatively blacklist the particular reference?\ Thanks, David -- Lift, the simply functional web frameworkhttp://liftweb.net Beginning Scalahttp://www.apress.com/book/view/1430219890 Follow me:http://twitter.com/dpp Surf the harmonics -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=. -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.comliftweb%2bunsubscr...@googlegroups.com . For more options, visit this group at http://groups.google.com/group/liftweb?hl=. -- Lift, the simply functional web frameworkhttp://liftweb.net Beginning Scalahttp://www.apress.com/book/view/1430219890 Follow me:http://twitter.com/dpp Surf the harmonics -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=.
[Lift] Re: intro to lift-json?
Hi, There's several ways to get values from JSON. 1. Use LINQ style query comprehension: for { JField(bar, JInt(x)) - json } yield x 2. Extract values with case classes implicit val formats = net.liftweb.json.DefaultFormats case class Foo(foo: Bar) case class Bar(bar: Int) json.extract[Foo] 3. XPath style val JField(bar, JInt(x)) = json \ foo \ bar Cheers Joni On 19 marras, 22:20, harryh har...@gmail.com wrote: Is there a basic intro to lift-json floating around anywhere? I'm having a bit of trouble getting started with a couple basic things. For example if a have a JObject that corresponds to: { foo : { bar : 999 } } How do I get the 999 (as an int) out of the JObject? I'm sure this is simple, just a bit confused on the basics. -harryh -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=.
[Lift] Re: Call it Lift 2.0
Hi, I will look into adding Box support. Cheers Joni On 19 marras, 21:24, David Pollak feeder.of.the.be...@gmail.com wrote: On Tue, Nov 17, 2009 at 10:06 PM, Joni Freeman freeman.j...@gmail.comwrote: On 18 marras, 01:10, David Pollak feeder.of.the.be...@gmail.com wrote: I'd like to see the JSON stuff moved from Option to Box, but that's Joni's call. Hi, I do not agree. We have quite a lot of lift-json users who do not yet use other parts of Lift, and Box is not a familiar construct outside of Lift. I really like to keep it that way. But could lift REST APIs wrap the lib to provide more Liftesque API? It's more of a return-type issue. The reason I created Box in the first place is that Option doesn't give you the ability to capture reasons for None (yeah, there's Either... although there wasn't when I introduced Box [Can at the time], but you can't use Either in a for comprehension). In reviewing the JSON code, there's actually nothing that I'd change in the APIs. I would support Box everywhere there's support for Option (serializing/deserializing and implicit helpers). Cheers Joni -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.comliftweb%2bunsubscr...@googlegroups.com . For more options, visit this group at http://groups.google.com/group/liftweb?hl=. -- Lift, the simply functional web frameworkhttp://liftweb.net Beginning Scalahttp://www.apress.com/book/view/1430219890 Follow me:http://twitter.com/dpp Surf the harmonics -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=.
[Lift] Re: Call it Lift 2.0
On 18 marras, 01:10, David Pollak feeder.of.the.be...@gmail.com wrote: I'd like to see the JSON stuff moved from Option to Box, but that's Joni's call. Hi, I do not agree. We have quite a lot of lift-json users who do not yet use other parts of Lift, and Box is not a familiar construct outside of Lift. I really like to keep it that way. But could lift REST APIs wrap the lib to provide more Liftesque API? Cheers Joni -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=.
[Lift] Re: Building Json result from a Map - tranforming a map into a list of new objects
Hi, One idiom for deconstructing a Map is to use a pattern match: myMap.map { case (k, v) = ... }. For instance: val json = (books - books.map { b = (id - b.id) ~ (tags - b.tags.map { case (k, v) = JField(k, v) }.toList) } ) Note, the explicit call toList is required since JsonDSL provides an implicit conversion from List[JField] to JObject (not from Iterable [JField]). Cheers Joni On 16 marras, 08:44, Tate jones.t...@gmail.com wrote: Hi all, I am pretty new to Scala and Lift so this question may not be pitched or explained correctly. I have an abstract class called Book that is created via Object Book. No troubles with this. abstract class Book { val tags : Map[String,String] val id : String } I wish to serialize this to a Json response, but I am having troubles resolving the serialization of the Map (tags) to a simple name value pair. eg. Map(Title - RedHat Unleashed, Category -OS) Json response. book: { id: ID1234, tags: { Title: RedHat Unleased, Category: OS } } val json = (books - books.map { b = (id - b.id) ~ (tags - b.tags.map { t = == this is where I need to create a List(JsonAST.JField(key,value)...)) from the map } ) } ) This is probably a general Scala question with maps, but I having difficult finding good examples that transform a map into a list with new object content. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to liftweb@googlegroups.com To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~--~~~~--~~--~--~---
[Lift] Re: Build Broken?
Hi, Can you send me surefire test result file at: lift-base/lift-json/target/surefire-reports/TEST- net.liftweb.json.XmlExamplesTest.xml All tests pass on my machine (Ubuntu 8.10, jdk1.6.0_10, Maven 2.0.9), but I will investigate why it fails on your setup. You can send the file directly to me, not sure if Google Groups accepts attachments. Cheers Joni On 7 marras, 07:22, aw anth...@whitford.com wrote: OK, found Hudson: http://hudson.scala-tools.org/job/Lift/ But now if that isn't broken, why is my fresh clone failing? --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to liftweb@googlegroups.com To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~--~~~~--~~--~--~---
[Lift] Re: Build Broken?
Thanks for the test results. It looked like a charset problem in unit test. I changed the assertion in test to use more robust case class comparison instead of String comparison. Please let us know if this fixes the build on your machine. Committers, I pushed this small fix directly into master, skipping Review Board. Please let me know if this is not allowed even if the change is very small and just for unit tests. Cheers Joni On 7 marras, 07:22, aw anth...@whitford.com wrote: OK, found Hudson: http://hudson.scala-tools.org/job/Lift/ But now if that isn't broken, why is my fresh clone failing? --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to liftweb@googlegroups.com To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~--~~~~--~~--~--~---
[Lift] Re: Possible bug in xml to json conversion
No problem Jonathan. We already have a fix for that bug so opening a report is not necessary. The fix is now being reviewed by other commiters: http://reviewboard.liftweb.net/r/69/diff/#index_header Cheers Joni On 2 marras, 07:00, Jonathan Ferguson j...@spiralarm.com wrote: Thanks for the update Joni and sorry for not getting back sooner. I'll try the code change you've suggested. Should I open a bug for the final example? Cheers Jono 2009/10/28 Joni Freeman freeman.j...@gmail.com Hi Jonathan, Current toJson conversion does not support this case very well. The transformation rule is such that from each leaf XML element a JSON field is generated. statsfoo/stats - stats:foo And if that leaf element contains attributes we do not convert it automatically to JSON object as you expected. Instead, another field at same level is created: stats count=0foo/stats - stats:foo count:0 In your case the leaf node is empty, therefore you will get a field with null value: stats count=0/stats - stats:null count:0 You can fix this for instance by postprocessing the generated JSON. In this case it is a bit involved and verbose (example below fixes 'stats' element, similar conversion is required for 'messages' element): val json = toJson(xml1) map { case JField(count, JString(count)) = JObject(JField(count, JInt (count.toInt)) :: Nil) // lift to object case JField(stats, _) = JNothing // remove null field case x = x } map { case JField(count, x: JObject) = JField(stats, x) // rename field count to stats case x = x } Note, the conversion rule which you expected is a perfectly valid conversion too. The rationale behind the current rule is that it never makes conversions which changes resulting JSON structure when attributes are missing. It is therefore more predictable. This blog post summarizes some other valid conversion rules http://onwebdevelopment.blogspot.com/2008/05/converting-xml-to-json.html We could add support for other conversion rules if there's a strong pressure to do so. But my current preference is to use a simple rule and then handle corner cases using transformation pipelines (using 'map' function). PS. The very last example you gave contains a bug which I try to nail down today. XML is parsed differently when all elements are in same line. Thanks for good examples! Cheers Joni On 28 loka, 09:24, Jonathan Ferguson j...@spiralarm.com wrote: Depending on the structure of the XML, attributes and child elements are being lost. This can be seen in example 4, where the attribute expiry_date and the child element status have been dropped. It would also appear when XML is being converted to JSON attributes are being flattened to elements. I'm not sure if this is expected or not, this can be seen in examples 1,2 3. The child element status with attribute count is converted to two attributes status with a value of null and count with the correct value. To test I added the following before the closing brace of XmlExamplesTest.scala in lift-json. Is this a bug or my error ? Cheers Jono P.S I've noticed this could be related to the thread Possible lift- json bug in Xml.toJson http://groups.google.com/group/liftweb/browse_thread/thread/47c581d63... /* Test */ import scala.xml.Node def xml2Json(xml:Node):String = { val json = toJson(xml) compact(render(json)) } XML to JSON Example with multiple attributes, multiple nested elements in { xml2Json(xml1) mustEqual expected1 } XML to JSON Example with multiple attributes, multiple nested elements in { xml2Json(xml2) mustEqual expected2 } XML to JSON Example with one attribute, multiple nested elements in { xml2Json(xml3) mustEqual expected3 } XML to JSON Example with one attribute, one nested element in { xml2Json(xml4) mustEqual expected4 } val xml1 = message expiry_date=20091126 text=text word=ant self=mestats count=0/statsmessages href=https:// domain.com/message/ant/messages/message val expected1 = {message:{expiry_date: 20091126,text:text,word:ant,self:me,stats:{count: 0},messages:{href:https://domain.com/message/ant}}}; val actual1 = {message: {expiry_date:20091126,word:ant,text:text,self:me,stats:null,count:0,messages:null,href:https:// domain.com/message/ant}} val xml2 = message expiry_date=20091126 text=text word=ant self=mestats count=0/statsmessages href=https:// domain.com/message/ant/messages/message val expected2 = {message:{expiry_date: 20091126,text:text,word:ant,self:me,stats:{count: 0},messages:{href:https://domain.com/message/ant}}}; val actual2 = {message: {expiry_date:20091126,word:ant,text:text,self:me,stats:null,count:0,messages:null,href:https:// domain.com/message/ant}} val xml3 = message expiry_date
[Lift] Re: lift-json serialization primitive types
Hi, Custom serialization and deserialization functions are now supported in trunk. Please see updated docs in section Serializing non- supported types: http://github.com/dpp/liftweb/tree/master/lift-base/lift-json/ Cheers Joni On 25 loka, 14:27, Christophe Dehlinger christophedehlin...@gmail.com wrote: Hi, Is there a way to configure lift-json's case class serialization so that it uses Joda DateTimes instead of java.util.Date ? I'd like to known how to make the simple following code work as expected: import net.liftweb.json._ import org.joda.time._ case class MyCaseClass(dt: DateTime) object TestMain { def main(args: Array[String]) { implicit val formats = DefaultFormats println(Serialization.read[MyCaseClass]({ dt : 2009-10-25T12:50:37.560+01:00 })) println(Serialization.write(MyCaseClass(new DateTime))) } } (running this code yields: MyCaseClass(2009-10-25T12:57:03.366+01:00) -- current date when the program was run, not the date in the code {} ) More generally, is there a way to customize lift-json's serialization mappings, in particular the types lift-json sees as primitive ? The class I'm actually interested in serializing has many fields whose type is a non-case class MyRichFloat with a single Float field. It would be really nice if I could (de)serialize these into JSON floats. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to liftweb@googlegroups.com To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~--~~~~--~~--~--~---
[Lift] Re: Possible bug in xml to json conversion
Hi Jonathan, Current toJson conversion does not support this case very well. The transformation rule is such that from each leaf XML element a JSON field is generated. statsfoo/stats - stats:foo And if that leaf element contains attributes we do not convert it automatically to JSON object as you expected. Instead, another field at same level is created: stats count=0foo/stats - stats:foo count:0 In your case the leaf node is empty, therefore you will get a field with null value: stats count=0/stats - stats:null count:0 You can fix this for instance by postprocessing the generated JSON. In this case it is a bit involved and verbose (example below fixes 'stats' element, similar conversion is required for 'messages' element): val json = toJson(xml1) map { case JField(count, JString(count)) = JObject(JField(count, JInt (count.toInt)) :: Nil) // lift to object case JField(stats, _) = JNothing // remove null field case x = x } map { case JField(count, x: JObject) = JField(stats, x) // rename field count to stats case x = x } Note, the conversion rule which you expected is a perfectly valid conversion too. The rationale behind the current rule is that it never makes conversions which changes resulting JSON structure when attributes are missing. It is therefore more predictable. This blog post summarizes some other valid conversion rules http://onwebdevelopment.blogspot.com/2008/05/converting-xml-to-json.html We could add support for other conversion rules if there's a strong pressure to do so. But my current preference is to use a simple rule and then handle corner cases using transformation pipelines (using 'map' function). PS. The very last example you gave contains a bug which I try to nail down today. XML is parsed differently when all elements are in same line. Thanks for good examples! Cheers Joni On 28 loka, 09:24, Jonathan Ferguson j...@spiralarm.com wrote: Depending on the structure of the XML, attributes and child elements are being lost. This can be seen in example 4, where the attribute expiry_date and the child element status have been dropped. It would also appear when XML is being converted to JSON attributes are being flattened to elements. I'm not sure if this is expected or not, this can be seen in examples 1,2 3. The child element status with attribute count is converted to two attributes status with a value of null and count with the correct value. To test I added the following before the closing brace of XmlExamplesTest.scala in lift-json. Is this a bug or my error ? Cheers Jono P.S I've noticed this could be related to the thread Possible lift- json bug in Xml.toJsonhttp://groups.google.com/group/liftweb/browse_thread/thread/47c581d63... /* Test */ import scala.xml.Node def xml2Json(xml:Node):String = { val json = toJson(xml) compact(render(json)) } XML to JSON Example with multiple attributes, multiple nested elements in { xml2Json(xml1) mustEqual expected1 } XML to JSON Example with multiple attributes, multiple nested elements in { xml2Json(xml2) mustEqual expected2 } XML to JSON Example with one attribute, multiple nested elements in { xml2Json(xml3) mustEqual expected3 } XML to JSON Example with one attribute, one nested element in { xml2Json(xml4) mustEqual expected4 } val xml1 = message expiry_date=20091126 text=text word=ant self=mestats count=0/statsmessages href=https:// domain.com/message/ant/messages/message val expected1 = {message:{expiry_date: 20091126,text:text,word:ant,self:me,stats:{count: 0},messages:{href:https://domain.com/message/ant}}}; val actual1 = {message: {expiry_date:20091126,word:ant,text:text,self:me,stats:null,count:0,messages:null,href:https:// domain.com/message/ant}} val xml2 = message expiry_date=20091126 text=text word=ant self=mestats count=0/statsmessages href=https:// domain.com/message/ant/messages/message val expected2 = {message:{expiry_date: 20091126,text:text,word:ant,self:me,stats:{count: 0},messages:{href:https://domain.com/message/ant}}}; val actual2 = {message: {expiry_date:20091126,word:ant,text:text,self:me,stats:null,count:0,messages:null,href:https:// domain.com/message/ant}} val xml3 = message expiry_date=20091126stats count=0/ statsmessages href=https://domain.com/message/ant;/messages/ message val expected3 = {message:{expiry_date:20091126,stats: {count:0},messages:{href:https://domain.com/message/ant}}}; val actual3 = {message: {expiry_date:20091126,stats:null,count:0,messages:null,href:https:// domain.com/message/ant}} val xml4 = message expiry_date=20091126stats count=0/ stats/message val expected4 = {message:{expiry_date:20091126,stats: {count:0}}} val actual4 = {message:} --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Lift group. To post to this group,
[Lift] Re: lift-json serialization primitive types
Hi, Serializing joda-time is not supported. Last week a type hint mechanism was added to support serialization of polymorphic Lists. This could be generalized a bit so that users can provide de-/ serializers for any type. This could be done for instance using a pair of partial functions. Something like: type TypeHint = String def serialize: PartialFunction[Any, JValue] def deserialize: PartialFunction[(TypeHint, JValue), Any] Then a support to serialize joda-time DateTime could be implemented as: def serialize(a: Any) = a match { case d: DateTime = JString(t, toString(d)) } def deserialize(hint: TypeHint, json: JValue) = (hint, json) match { case (DateTime, JString(t, JString(t)) = mkDateTime(t) } I'm in a middle of something else right now but will look into this next. Cheers Joni On 25 loka, 14:27, Christophe Dehlinger christophedehlin...@gmail.com wrote: Hi, Is there a way to configure lift-json's case class serialization so that it uses Joda DateTimes instead of java.util.Date ? I'd like to known how to make the simple following code work as expected: import net.liftweb.json._ import org.joda.time._ case class MyCaseClass(dt: DateTime) object TestMain { def main(args: Array[String]) { implicit val formats = DefaultFormats println(Serialization.read[MyCaseClass]({ dt : 2009-10-25T12:50:37.560+01:00 })) println(Serialization.write(MyCaseClass(new DateTime))) } } (running this code yields: MyCaseClass(2009-10-25T12:57:03.366+01:00) -- current date when the program was run, not the date in the code {} ) More generally, is there a way to customize lift-json's serialization mappings, in particular the types lift-json sees as primitive ? The class I'm actually interested in serializing has many fields whose type is a non-case class MyRichFloat with a single Float field. It would be really nice if I could (de)serialize these into JSON floats. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to liftweb@googlegroups.com To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~--~~~~--~~--~--~---
[Lift] Re: A Critique On Lift
I love it too. While it is used in many different places it always means stuff that I do not care to name. BTW. high priest of the lambda calculus loves it too :) It has its roots in Haskell... http://channel9.msdn.com/shows/Going+Deep/C9-Lectures-Dr-Erik-Meijer-Functional-Programming-Fundamentals-Chapter-4-of-13/ Cheers Joni On 23 loka, 09:48, Jonas Bonér jbo...@gmail.com wrote: I love the _ operator. 2009/10/22 Timothy Perrett timo...@getintheloop.eu: I think this is a bit of a running joke in the scala comunity right now - your right, underscore really does have a number of meanings; I think this will be changed in some future Scala release. Your also forgetting: import some.package._ Cheers, Tim On 22 Oct 2009, at 12:57, tiro wrote: underscore. At least four different uses: - it for defining anonymous functions like above - default value - matching placeholder whose value is ignored - use for constructing setter method names boolean functions (empty_?) -- Jonas Bonér twitter: @jboner blog: http://jonasboner.com work: http://scalablesolutions.se code: http://github.com/jboner code: http://akkasource.org also: http://letitcrash.com --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to liftweb@googlegroups.com To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~--~~~~--~~--~--~---
[Lift] Re: Including the class name in the JSON field
Hi, Yes I'll put these to Review Board soon. I just add some documentation, rerun serialization benchmark and do a little bit testing. Unless someone wants to discuss details/alternatives/etc more... Cheers Joni On 20 loka, 18:22, Derek Chen-Becker dchenbec...@gmail.com wrote: Are you putting these changes in Review Board, or is this still experimental work? Derek On Mon, Oct 19, 2009 at 9:02 AM, Joni Freeman freeman.j...@gmail.comwrote: Added a way to change how 'type hints' are processed. The default is NoTypeHints which will never output 'jsonClass' field. Then there's ShortTypeHints and FullTypeHints. implicit val formats = Serialization.formats(ShortTypeHints(classOf [Fish] :: classOf[Dog] :: Nil)) - { jsonClass:Fish, ... } implicit val formats = Serialization.formats(FullTypeHints(classOf [Animal] :: Nil)) - { jsonClass:com.example.Fish, ... } TypeHints trait can be used to reduce couplings (as suggested by Steve). Cheers Joni On 18 loka, 23:46, Joni Freeman freeman.j...@gmail.com wrote: There's now some support to deserialize parameterized types in that experimental branch. For instance, these all work: implicit val formats = Serialization.formats(TypeHints(classOf [Animal] :: Nil)) case class Animals(animals: List[Animal]) trait Animal case class Dog(name: String) extends Animal case class Fish(weight: Double) extends Animal case class Objs(objects: List[Obj[_]]) case class Obj[A](a: A) val animals = Animals(Dog(pluto) :: Fish(1.2) :: Dog(devil) :: Nil) val ser = swrite(animals) read[Animals](ser) mustEqual animals val objs = Objs(Obj(Fish(1.2)) :: Obj(Dog(pluto)) :: Nil) val ser = swrite(objs) read[Objs](ser) mustEqual objs val t: (Animal, Animal) = (Fish(1.5), Dog(pluto)) val ser = swrite(t) read[(Animal, Animal)](ser) mustEqual t The first line (implicit val formats ...) configures the serialization to output type hint (jsonClass field) for all instances of class Animal. This is required since above examples use Animal's in polymorphic way. Comments? Cheers Joni On 18 loka, 01:27, David Pollak feeder.of.the.be...@gmail.com wrote: On Sat, Oct 17, 2009 at 7:54 AM, Joni Freeman freeman.j...@gmail.com wrote: I've been thinking this feature today a bit too. Marius raises an important point. Adding type information and more complex serialization scheme will introduce couplings, making it for instance more difficult to deserializeJSONusing a different language or toolkit. On a positive side, we might get support for other parameterized types too (tuples for instance). I pushed an experimental branch (joni_issue_108) which contains serialization part of this feature (the easy part really). It adds 'jsonClass' field to objects. case class Animals(animals: List[Animal]) trait Animal case class Dog(name: String) extends Animal case class Fish(weight: Double) extends Animal scala write(Animals(Dog(pluto) :: Fish(1.2) :: Dog(devil) :: Nil)) res0: String = {jsonClass:Animals,animals: [{jsonClass:Dog,name:pluto},{jsonClass:Fish,weight:1.2}, {jsonClass:Dog,name:devil}]} Possible actions: * Do not support parameterized types (status quo) + Simple scheme, easy to serialize in language agnostic way - Limited I like this option. I'm not looking for a full Java serialization style solution. But having hints as to the type of the particularJSONobject would be helpful. Being able to register a jsonClass - Scala class deserializer makes sense. Being able to specify a Scala class - class name is a good thing (with the default being the actual class name without the package). * Add full type information when serializing/deserializing + Opens possibility to deserialize polymorphic types + Deserialization can be done without any explicit type information (read(...) vs. read[ExpectedType](...)) - Introduces couplings - This is still not a generic serialization solution, there's still a lot of Scala classes which can't be deserialized * Support both schemes + Moar choice - Choice it not necessarily a good thing (adds complexity etc.) Cheers Joni On 17 loka, 11:40, Marius marius.dan...@gmail.com wrote: Hmmm ... I wonder if heterogeneous lists should be supported. I also wonder if type knowledge inJSONis a good thing to do as it seems to me that we're bringing knowledge from another domain creating couplings. I'm not sure if there is a different way to solve this ... it just doesn't feel completely right to me ... but this doesn't necessarily mean it is not right :) Br's, Marius On Oct 15, 1:47 am, David Pollak feeder.of.the.be...@gmail.com wrote: Folks
[Lift] Re: Including the class name in the JSON field
Added a way to change how 'type hints' are processed. The default is NoTypeHints which will never output 'jsonClass' field. Then there's ShortTypeHints and FullTypeHints. implicit val formats = Serialization.formats(ShortTypeHints(classOf [Fish] :: classOf[Dog] :: Nil)) - { jsonClass:Fish, ... } implicit val formats = Serialization.formats(FullTypeHints(classOf [Animal] :: Nil)) - { jsonClass:com.example.Fish, ... } TypeHints trait can be used to reduce couplings (as suggested by Steve). Cheers Joni On 18 loka, 23:46, Joni Freeman freeman.j...@gmail.com wrote: There's now some support to deserialize parameterized types in that experimental branch. For instance, these all work: implicit val formats = Serialization.formats(TypeHints(classOf [Animal] :: Nil)) case class Animals(animals: List[Animal]) trait Animal case class Dog(name: String) extends Animal case class Fish(weight: Double) extends Animal case class Objs(objects: List[Obj[_]]) case class Obj[A](a: A) val animals = Animals(Dog(pluto) :: Fish(1.2) :: Dog(devil) :: Nil) val ser = swrite(animals) read[Animals](ser) mustEqual animals val objs = Objs(Obj(Fish(1.2)) :: Obj(Dog(pluto)) :: Nil) val ser = swrite(objs) read[Objs](ser) mustEqual objs val t: (Animal, Animal) = (Fish(1.5), Dog(pluto)) val ser = swrite(t) read[(Animal, Animal)](ser) mustEqual t The first line (implicit val formats ...) configures the serialization to output type hint (jsonClass field) for all instances of class Animal. This is required since above examples use Animal's in polymorphic way. Comments? Cheers Joni On 18 loka, 01:27, David Pollak feeder.of.the.be...@gmail.com wrote: On Sat, Oct 17, 2009 at 7:54 AM, Joni Freeman freeman.j...@gmail.comwrote: I've been thinking this feature today a bit too. Marius raises an important point. Adding type information and more complex serialization scheme will introduce couplings, making it for instance more difficult to deserializeJSONusing a different language or toolkit. On a positive side, we might get support for other parameterized types too (tuples for instance). I pushed an experimental branch (joni_issue_108) which contains serialization part of this feature (the easy part really). It adds 'jsonClass' field to objects. case class Animals(animals: List[Animal]) trait Animal case class Dog(name: String) extends Animal case class Fish(weight: Double) extends Animal scala write(Animals(Dog(pluto) :: Fish(1.2) :: Dog(devil) :: Nil)) res0: String = {jsonClass:Animals,animals: [{jsonClass:Dog,name:pluto},{jsonClass:Fish,weight:1.2}, {jsonClass:Dog,name:devil}]} Possible actions: * Do not support parameterized types (status quo) + Simple scheme, easy to serialize in language agnostic way - Limited I like this option. I'm not looking for a full Java serialization style solution. But having hints as to the type of the particularJSONobject would be helpful. Being able to register a jsonClass - Scala class deserializer makes sense. Being able to specify a Scala class - class name is a good thing (with the default being the actual class name without the package). * Add full type information when serializing/deserializing + Opens possibility to deserialize polymorphic types + Deserialization can be done without any explicit type information (read(...) vs. read[ExpectedType](...)) - Introduces couplings - This is still not a generic serialization solution, there's still a lot of Scala classes which can't be deserialized * Support both schemes + Moar choice - Choice it not necessarily a good thing (adds complexity etc.) Cheers Joni On 17 loka, 11:40, Marius marius.dan...@gmail.com wrote: Hmmm ... I wonder if heterogeneous lists should be supported. I also wonder if type knowledge inJSONis a good thing to do as it seems to me that we're bringing knowledge from another domain creating couplings. I'm not sure if there is a different way to solve this ... it just doesn't feel completely right to me ... but this doesn't necessarily mean it is not right :) Br's, Marius On Oct 15, 1:47 am, David Pollak feeder.of.the.be...@gmail.com wrote: Folks, What are thoughts on including (perhaps optionally) the name of the case class in an additionalJSONfield so that one can reconstruct a list that contains many different types? Thanks, David -- Lift, the simply functional web frameworkhttp://liftweb.net Beginning Scalahttp://www.apress.com/book/view/1430219890 Follow me:http://twitter.com/dpp Surf the harmonics -- Lift, the simply functional web frameworkhttp://liftweb.net Beginning Scalahttp://www.apress.com/book/view/1430219890 Follow me:http://twitter.com/dpp Surf the harmonics
[Lift] Re: Including the class name in the JSON field
I've been thinking this feature today a bit too. Marius raises an important point. Adding type information and more complex serialization scheme will introduce couplings, making it for instance more difficult to deserialize JSON using a different language or toolkit. On a positive side, we might get support for other parameterized types too (tuples for instance). I pushed an experimental branch (joni_issue_108) which contains serialization part of this feature (the easy part really). It adds 'jsonClass' field to objects. case class Animals(animals: List[Animal]) trait Animal case class Dog(name: String) extends Animal case class Fish(weight: Double) extends Animal scala write(Animals(Dog(pluto) :: Fish(1.2) :: Dog(devil) :: Nil)) res0: String = {jsonClass:Animals,animals: [{jsonClass:Dog,name:pluto},{jsonClass:Fish,weight:1.2}, {jsonClass:Dog,name:devil}]} Possible actions: * Do not support parameterized types (status quo) + Simple scheme, easy to serialize in language agnostic way - Limited * Add full type information when serializing/deserializing + Opens possibility to deserialize polymorphic types + Deserialization can be done without any explicit type information (read(...) vs. read[ExpectedType](...)) - Introduces couplings - This is still not a generic serialization solution, there's still a lot of Scala classes which can't be deserialized * Support both schemes + Moar choice - Choice it not necessarily a good thing (adds complexity etc.) Cheers Joni On 17 loka, 11:40, Marius marius.dan...@gmail.com wrote: Hmmm ... I wonder if heterogeneous lists should be supported. I also wonder if type knowledge in JSON is a good thing to do as it seems to me that we're bringing knowledge from another domain creating couplings. I'm not sure if there is a different way to solve this ... it just doesn't feel completely right to me ... but this doesn't necessarily mean it is not right :) Br's, Marius On Oct 15, 1:47 am, David Pollak feeder.of.the.be...@gmail.com wrote: Folks, What are thoughts on including (perhaps optionally) the name of the case class in an additional JSON field so that one can reconstruct a list that contains many different types? Thanks, David -- Lift, the simply functional web frameworkhttp://liftweb.net Beginning Scalahttp://www.apress.com/book/view/1430219890 Follow me:http://twitter.com/dpp Surf the harmonics --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to liftweb@googlegroups.com To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~--~~~~--~~--~--~---
[Lift] Re: JSON... deserializing lists of parameterized case classes
Hi David, Please file a ticket, serialization does not support polymorphic Lists yet. It requires that we add type information into JSON. Something like: { who: [ { jsonClass = example.Foo1 ... }, { jsonClass = example.Foo2 ... } ] } Cheers Joni On Oct 16, 1:11 am, David Pollak feeder.of.the.be...@gmail.com wrote: Howdy, I've got something like: final case class Foo[T](name: String) final case class ManyFoos(who: List[Foo[_]])) If I do JSON serialization/deserialization using lift-json, of an instance of ManyFoos, the deserialization stuff throws an exception. Is this expected or should I file a ticket? Thanks, David -- Lift, the simply functional web frameworkhttp://liftweb.net Beginning Scalahttp://www.apress.com/book/view/1430219890 Follow me:http://twitter.com/dpp Surf the harmonics --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to liftweb@googlegroups.com To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~--~~~~--~~--~--~---
[Lift] Re: Possible lift-json bug in Xml.toJson
Hi, I fixed this but it will slip M6. You can build a fixed version from branch if you need it now. Please see the changeset 'Scala XML support...': http://github.com/dpp/liftweb/commits/joni_wip_xml Cheers Joni On Oct 5, 9:22 pm, harryh har...@gmail.com wrote: Xml.toJson (in M5) is converting this: iconhttp://harryh.org/img/icons/foo.png/icon to this: JField(icon, JObject(Nil)) Is there some special handling of URLs going on here that might be causing me problems? -harryh --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to liftweb@googlegroups.com To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~--~~~~--~~--~--~---
[Lift] Re: lift-json's extract and Mapper
Hi Peter, To select multiple packets you need to first select the objects within the array. Like this: for { JObject(packet) - parse(s) JField(node, JString(node)) - packet JField(dt, JInt(dt)) - packet JField(temp, JDouble(temp)) - packet } yield // construct Packet here Cheers Joni On Oct 5, 2:13 am, Peter Robinett pe...@bubblefoundry.com wrote: Thanks, Joni. I've been playing with just that for comprehension syntax over the weekend. How would I do it if I had multiple packets? { packets: [ { node: 00:1D:C9:00:04:9F, dt: 1254553581405, temp: 27.5 }, { node: 00:1D:C9:00:04:9E, dt: 1254553582405, temp: 24.3 } ] } I've had some problems iterating across the parsed results. If I do: for { json - parse(s) JField(node, JString(node)) - json JField(dt, JInt(dt)) - json JField(temp, JDouble(temp)) - json } yield // construct Packet here I will end up with 8 Packets. Should I be doing something like JArray (json) - parse(s)? Thanks for your help, Peter On Oct 4, 3:08 pm, Joni Freeman freeman.j...@gmail.com wrote: I don't know how hard would it be to add this feature, so I don't know if this is a reasonable request. This would make making JSON API endpoints really easy for me and I hope for other people too. This certainly sounds like a reasonable feature request, I will take a deeper look at it. Meanwhile, you can use tmp case class as Kevin noted, or use for- comprehension to query the json. Something like: { packet: { node: 00:1D:C9:00:04:9F, dt: 1254553581405, temp: 27.5 } } val json = parse(s) for { JField(node, JString(node)) - json JField(dt, JInt(dt)) - json JField(temp, JDouble(temp)) - json } yield // construct Packet here That's a bit verbose but quite flexible. This test case contains more query examples:http://github.com/dpp/liftweb/blob/master/lift-json/src/test/scala/ne... Cheers Joni --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to liftweb@googlegroups.com To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~--~~~~--~~--~--~---
[Lift] Re: lift-json and attributes
Thanks Richard! This is a feature request and I just committed an implementation to my branch. I modified existing example to contain few attributes to show how they are mapped: http://github.com/dpp/liftweb/blob/joni_wip_xml/lift-json/src/test/scala/net/liftweb/json/XmlExamples.scala If other committers give it the green light I will push it to master. Cheers Joni On Oct 5, 5:41 pm, Richard Dallaway dalla...@gmail.com wrote: Loving the new lift-json code. We've been producing XML for a REST API, and now need to produce JSON. lift-json to the rescue, except...the Xml converter doesn't handle attributes: scala val xml = user id=7nameBert/name/user xml: scala.xml.Elem = user id=7nameBert/name/user scala val json = toJson(xml) json: net.liftweb.json.JsonAST.JValue = JObject(List(JField(user,JObject(List(JField(name,JString(Bert))) scala JsonDSL.compact(JsonAST.render(json)) res5: String = {user:{name:Bert}} I'd expect res5 to be something like: {user:{id:7,name:Bert}} I'm either missing a clue, or this is a feature request. I can see there's ambiguity in how you might map the above JSON back to XML with attributes, but it seems reasonable that if you have XML + attributes they would be present in a JSON representation. Thank you Richard --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to liftweb@googlegroups.com To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~--~~~~--~~--~--~---
[Lift] Re: Possible lift-json bug in Xml.toJson
Yes, that's exactly what happens here. David, do you know if this should be considered a bug in Scala XML or should lift-json be able to merge those Text() nodes? Cheers Joni On Oct 5, 9:46 pm, David Pollak feeder.of.the.be...@gmail.com wrote: Hmmm looks like there might be multiple Text() nodes in the icon node and the parser isn't picking them up as one piece of text. Might be worthy of a ticket. On Mon, Oct 5, 2009 at 11:31 AM, harryh har...@gmail.com wrote: More info. If the code that generates the XML looks like this: icon{http://harryh.org+theUri}/icon everything is fine, but it breaks when like this: iconhttp://harryh.org{theUrl}/icon -harryh On Oct 5, 2:22 pm, harryh har...@gmail.com wrote: Xml.toJson (in M5) is converting this: iconhttp://harryh.org/img/icons/foo.png/icon to this: JField(icon, JObject(Nil)) Is there some special handling of URLs going on here that might be causing me problems? -harryh -- Lift, the simply functional web frameworkhttp://liftweb.net Beginning Scalahttp://www.apress.com/book/view/1430219890 Follow me:http://twitter.com/dpp Surf the harmonics --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to liftweb@googlegroups.com To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~--~~~~--~~--~--~---
[Lift] Re: lift-json's extract and Mapper
I don't know how hard would it be to add this feature, so I don't know if this is a reasonable request. This would make making JSON API endpoints really easy for me and I hope for other people too. This certainly sounds like a reasonable feature request, I will take a deeper look at it. Meanwhile, you can use tmp case class as Kevin noted, or use for- comprehension to query the json. Something like: { packet: { node: 00:1D:C9:00:04:9F, dt: 1254553581405, temp: 27.5 } } val json = parse(s) for { JField(node, JString(node)) - json JField(dt, JInt(dt)) - json JField(temp, JDouble(temp)) - json } yield // construct Packet here That's a bit verbose but quite flexible. This test case contains more query examples: http://github.com/dpp/liftweb/blob/master/lift-json/src/test/scala/net/liftweb/json/QueryExamples.scala Cheers Joni --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to liftweb@googlegroups.com To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~--~~~~--~~--~--~---
[Lift] Re: json extraction problem
Hi, I pasted this to scala console and it worked. I am pretty sure that the problem is that your case classes are inner classes. Inner classes get one extra implicit constructor parameter, a reference to the outer class (same way as in Java). You need to move those case classes away from enclosing class (to an object or package etc.). The error message is very bad in this case. I will fix it. Cheers Joni On Oct 1, 7:49 am, Lincoln linxbet...@gmail.com wrote: Hi, I've been playing around with lift-json and I keep running into basic problems. I'm hoping someone can point out my mistake. I'm using net.liftweb % lift-json % 1.1-M5 Here's the code I'm trying to run: implicit val formats = net.liftweb.json.DefaultFormats case class Name(first: String, last: String) case class User(name: Name, email: String) import net.liftweb.json.JsonParser._ val u = { import JsonDSL._ (name - (first - Lincoln) ~ (last - Hochberg) ) ~ (email - linxbet...@gmail.com)} val json = JsonDSL.pretty(JsonAST.render(u)) val jsonAST = JsonParser.parse(json) val user = jsonAST.extract[User] This blows up with the following exception: net.liftweb.json.MappingException: Parsed JSON values do not match with class constructor args= arg types= constructor=public pkg.TestSpec$$anonfun$1$$anonfun$apply$1(pkg.TestSpec$$anonfun$1) at net.liftweb.json.Extraction$.net$liftweb$json$Extraction$$fail(Extraction.scala:151) at net.liftweb.json.Extraction$.newInstance$1(Extraction.scala:72) at net.liftweb.json.Extraction$.build$1(Extraction.scala:84) at net.liftweb.json.Extraction$$anonfun$1.apply(Extraction.scala:84) at net.liftweb.json.Extraction$$anonfun$1.apply(Extraction.scala:84) at scala.List.flatMap(List.scala:1132) at net.liftweb.json.Extraction$.build$1(Extraction.scala:84) at net.liftweb.json.Extraction$$anonfun$1.apply(Extraction.scala:84) at net.liftweb.json.Extraction$$anonfun$1.apply(Extraction.scala:84) at scala.List.flatMap(List.scala:1132) at net.liftweb.json.Extraction$.build$1(Extraction.scala:84) at net.liftweb.json.Extraction$.extract0(Extraction.scala:109) at net.liftweb.json.Extraction$.extract(Extraction.scala:60) at net.liftweb.json.JsonAST$JValue.extract(Json.scala:109) at com.hotpotato.core.ops.TestSpec$$anonfun$1$$anonfun$apply$1.apply(TestSpec.scala:48) at com.hotpotato.core.ops.TestSpec$$anonfun$1$$anonfun$apply$1.apply(TestSpec.scala:14) at org.specs.specification.ExampleExecution$$anonfun$3$$anonfun$apply$1.apply(Example.scala:207) at org.specs.specification.Example.execute(Example.scala:121) at org.specs.specification.ExampleLifeCycle$class.executeTest(ExampleLifeCycle.scala:20) at org.specs.Specification.executeTest(Specification.scala:28) at org.specs.specification.Sus.executeTest(Sus.scala:147) at org.specs.specification.ExampleExecution$$anonfun$3.apply(Example.scala:207) at org.specs.specification.ExampleExecution$$anonfun$3.apply(Example.scala:194) at org.specs.specification.ExampleExecution$$anonfun$2.apply(Example.scala:185) at org.specs.specification.ExampleExecution.execute(Example.scala:227) at org.specs.specification.Example.execute(Example.scala:117) at org.specs.specification.Example.errors(Example.scala:143) at org.specs.specification.Sus$$anonfun$successes$1.apply(Sus.scala:122) at org.specs.specification.Sus$$anonfun$successes$1.apply(Sus.scala:122) at scala.List.filter(List.scala:859) at org.specs.specification.Sus.successes(Sus.scala:122) at org.specs.Specification$$anonfun$successes$1.apply(Specification.scala:84) at org.specs.Specification$$anonfun$successes$1.apply(Specification.scala:84) at scala.List.flatMap(List.scala:1132) at org.specs.Specification.successes(Specification.scala:84) at sbt.impl.SpecsRunner.sbt$impl$SpecsRunner$$reportSpecification(TestFrameworkImpl.scala:140) at sbt.impl.SpecsRunner.runTest(TestFrameworkImpl.scala:123) at sbt.BasicTestRunner.run(TestFramework.scala:38) at sbt.TestFramework$$anonfun$7$$anonfun$apply$8.runTest$1(TestFramework.scala:136) at sbt.TestFramework$$anonfun$7$$anonfun$apply$8$$anonfun$apply$9.apply(TestFramework.scala:147) at sbt.TestFramework$$anonfun$7$$anonfun$apply$8$$anonfun$apply$9.apply(TestFramework.scala:147) at sbt.NamedTestTask.run(TestFramework.scala:57) at sbt.ScalaProject$$anonfun$sbt$ScalaProject$$toTask$1.apply(ScalaProject.scala:167) at sbt.ScalaProject$$anonfun$sbt$ScalaProject$$toTask$1.apply(ScalaProject.scala:167) at sbt.TaskManager$Task.invoke(TaskManager.scala:62) at sbt.impl.RunTask.runTask(RunTask.scala:78) at sbt.impl.RunTask.sbt$impl$RunTask$$runIfNotRoot(RunTask.scala:63) at sbt.impl.RunTask$$anonfun$runTasksExceptRoot$3.apply(RunTask.scala:49) at sbt.impl.RunTask$$anonfun$runTasksExceptRoot$3.apply(RunTask.scala:49) at sbt.Distributor$Run$Worker$$anonfun$2.apply(ParallelRunner.scala:130) at sbt.Distributor$Run$Worker$$anonfun$2.apply(ParallelRunner.scala:130) at sbt.Control$.trapUnit(Control.scala:19) at
[Lift] Re: lift-json serialization
Tim, Extracted function is now in master. I renamed it as 'decompose' since it decomposes case class into JSON AST. Thanks again, Joni On Sep 21, 6:52 pm, Tim Nelson tnell...@gmail.com wrote: First of all thanks for a great library. I'm finding lift-json quite useful in my current project. I have a use case where I need to convert a case class into a JObject. The code is there, but it's wrapped inside the Serialization object. So, I took the liberty of moving the serialize method to the Extraction object and made it publicly accessible. You can see my changes here: http://github.com/eltimn/liftweb/commit/30310f4800b2aeb880b246e99dc79... It doesn't affect the current API at all and all tests passed. What do you think? Feel free to move it wherever you think it should be. As long as it's publicly accessible, I'll be happy. Thanks, Tim --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to liftweb@googlegroups.com To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~--~~~~--~~--~--~---
[Lift] Re: XML - JSON converter?
Hi, There is now improved XML support in lift master. See a short section in README: http://github.com/dpp/liftweb/tree/master/lift-json/ and some executable examples: http://github.com/dpp/liftweb/blob/master/lift-json/src/test/scala/net/liftweb/json/XmlExamples.scala Cheers Joni On Sep 2, 9:27 pm, harryh har...@gmail.com wrote: Is there anything built into lift that will doXML- JSON conversion? For example: foos foo id1/id nameHarry/name /foo foo id2/id nameDavid/name /foo /foos to: { foos: { foo: [{ id: 1, name: Harry }, { id: 2, name: David } ] } Just checking to see if there was something Lift friendly to do this before writing my own (or picking a java library to use). -harryh --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to liftweb@googlegroups.com To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~--~~~~--~~--~--~---
[Lift] Re: lift-json serialization
Hi Tim, Thanks for the kind words! The serialization functions should already be publicly accessible, you just need to import them into scope: import net.liftweb.json.Serialization.{read, write} val ser = write(...) val obj = read[..](ser) Cheers Joni On Sep 21, 6:52 pm, Tim Nelson tnell...@gmail.com wrote: First of all thanks for a great library. I'm finding lift-json quite useful in my current project. I have a use case where I need to convert a case class into a JObject. The code is there, but it's wrapped inside the Serialization object. So, I took the liberty of moving the serialize method to the Extraction object and made it publicly accessible. You can see my changes here: http://github.com/eltimn/liftweb/commit/30310f4800b2aeb880b246e99dc79... It doesn't affect the current API at all and all tests passed. What do you think? Feel free to move it wherever you think it should be. As long as it's publicly accessible, I'll be happy. Thanks, Tim --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to liftweb@googlegroups.com To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~--~~~~--~~--~--~---
[Lift] Re: lift-json serialization
Oh, I see the point now and agree that this is useful. Let's add thia to API. Thanks a lot! Cheers Joni On Sep 21, 6:52 pm, Tim Nelson tnell...@gmail.com wrote: First of all thanks for a great library. I'm finding lift-json quite useful in my current project. I have a use case where I need to convert a case class into a JObject. The code is there, but it's wrapped inside the Serialization object. So, I took the liberty of moving the serialize method to the Extraction object and made it publicly accessible. You can see my changes here: http://github.com/eltimn/liftweb/commit/30310f4800b2aeb880b246e99dc79... It doesn't affect the current API at all and all tests passed. What do you think? Feel free to move it wherever you think it should be. As long as it's publicly accessible, I'll be happy. Thanks, Tim --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to liftweb@googlegroups.com To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~--~~~~--~~--~--~---
[Lift] Re: Why isn't this a trait in lift-json?
On Sep 14, 8:14 am, Naftoli Gugenheim naftoli...@gmail.com wrote: Can't you require back ticks and name the case class members the same as in the JSON? This works pretty well, thanks for pointing out this solution! I added name demangling to support back ticks and removed @path annotation. It is no longer necessary since there is two workarounds (back ticks and map function). The relevant commit which needs to be reviewed: http://github.com/jonifreeman/liftweb/commit/b452c56f2d4d4b3e289cffdf389b862cfad4da98 Other pending commits which are not pushed to dpp's master yet and needs to be reviewed: http://github.com/jonifreeman/liftweb/commit/4dd150c089d834912b1025e350161aa23beb9fb9 http://github.com/jonifreeman/liftweb/commit/a6ce11916e0c08eb00769cbd7a358bf508c5f064 http://github.com/jonifreeman/liftweb/commit/18a667371271cb5a7a9fd1e6d26ec3d06010937d http://github.com/jonifreeman/liftweb/commit/cee2a1f41503f3e6865d1fd091b4c6aefee82b41 Cheers Joni --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to liftweb@googlegroups.com To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~--~~~~--~~--~--~---
[Lift] Re: Why isn't this a trait in lift-json?
Hi, That annotation is used to configure the json path when extracting values. By default the extraction code assumes that case class parameter names match with json field names. For instance these match: case class Foo(bar: String, baz: Int) { bar: qwerty, baz: 10 } But sometimes json field names can contain characters which are not allowed in Scala identifiers. For example: { foo-bar: qwerty, baz: 10 } Now, to able to extract this we have to somehow tell the extractor the exact path explicitly. Currently @path annotation is used for that: case class Foo(@path(foo-bar) bar: String, baz: Int) I don't see how a trait can accomplish this, maybe I'm missing something? The reason why it is in Java is that Scala annotations are not accessible at runtime. Cheers Joni On Sep 13, 11:03 pm, Timothy Perrett timo...@getintheloop.eu wrote: Just had a browse over the latest commit and found the following in path.java: @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface path { public String value(); } Any reason were not using a trait etc to complete the same functionality? Cheers, Tim --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to liftweb@googlegroups.com To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~--~~~~--~~--~--~---
[Lift] Re: Why isn't this a trait in lift-json?
Extending ClassfileAnnotation does not work at the moment. Excerpt from Programming Scala (http://programming-scala.labs.oreilly.com/ ch13.html): Another child of scala.Annotation that is intended to be a parent of other annotations is the trait scala.ClassfileAnnotation. It is supposed to be used for annotations that should have runtime retention, i.e., the annotations should be visible in the class file so they are available at runtime. However, actually using it with the JDK version of Scala results in compiler errors Hence, if you want runtime visibility, you have to implement the annotation in Java. Cheers Joni On Sep 14, 4:18 am, Josh Suereth joshua.suer...@gmail.com wrote: Scala does support annotations, they're just anemic at this point. I hadn't tried, but does extending ClassfileAnnotation allow runtime visibility? That would give you a pure scala implementation. If not, I think we need to rally for StaticAnnotation/ClassfileAnnotation to be joined by their future brother RuntimeAnnotation. - Josh On Sun, Sep 13, 2009 at 6:31 PM, marius d. marius.dan...@gmail.com wrote: On Sep 13, 3:15 pm, Joni Freeman freeman.j...@gmail.com wrote: Hi, That annotation is used to configure the json path when extracting values. By default the extraction code assumes that case class parameter names match with json field names. For instance these match: case class Foo(bar: String, baz: Int) { bar: qwerty, baz: 10 } But sometimes json field names can contain characters which are not allowed in Scala identifiers. For example: { foo-bar: qwerty, baz: 10 } Now, to able to extract this we have to somehow tell the extractor the exact path explicitly. Currently @path annotation is used for that: case class Foo(@path(foo-bar) bar: String, baz: Int) I don't see how a trait can accomplish this, maybe I'm missing something? The reason why it is in Java is that Scala annotations are not accessible at runtime. Right but I'd also suggest removing Java code from Lift stack. The above can be easily achieved by introducing a trait such as: case class Foo(bar: String with Nominator, baz: Int) Lift is a 100% Scala code with zero Java code. We also have strong opinions in the team that we should stay away from annotations. one option would be something like this: Lift would have : trait Nominator{ def name : String } In user's code: case class Foo(bar: String with MyNominator, baz: Int) trait MyNominator extends Nominator { def name = foo-bar } Yes it is more verbose then the annotation but IMHO it is more Scala- ish Lift-ish. Cheers Joni On Sep 13, 11:03 pm, Timothy Perrett timo...@getintheloop.eu wrote: Just had a browse over the latest commit and found the following in path.java: @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface path { public String value(); } Any reason were not using a trait etc to complete the same functionality? Cheers, Tim --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to liftweb@googlegroups.com To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~--~~~~--~~--~--~---
[Lift] Re: Why isn't this a trait in lift-json?
Hi, Here's another example. {lotto: { id: 5, winning-numbers: [2,45,34,23,7,5,3], draw-date: 2009-09-14T18:00:00Z, winners: [ {winner-id: 23, numbers: [2,45,34,23,3,5] }, {winner-id: 54, numbers:[52,3,12,11,18,22] } ] } } At the moment I'm extracting this with following case class structure. case class Winner(@path(winner-id) id: Long, numbers: List[Int]) case class Lotto(id: Long, @path(winning-numbers) winningNumbers: List[Int], winners: List[Winner], @path(draw-date) drawDate: Option[Date]) Using a trait approach it would be something like: case class Winner(id: Long with WinnerIdNominator, numbers: List[Int]) case class Lotto(id: Long, winningNumbers: List[Int] with WinningNumbersNominator, winners: List[Winner], drawDate: Option[Date] with DrawDateNominator) trait WinnerIdNominator extends Nominator { def name = winner-id } trait WinningNumbersNominator extends Nominator { def name = winning-numbers } trait DrawDateNominator extends Nominator { def name = draw-date } Now, there's some problems. 1. Mixin a trait with a primitive fails: scala case class Winner(id: Long with WinnerIdNominator, numbers: List [Int]) console:5: error: ambiguous reference to overloaded definition, both method == in class Object of type (AnyRef)Boolean and method == in class Long of type (Long)Boolean match argument types (Long with WinnerIdNominator) case class Winner(id: Long with WinnerIdNominator, numbers: List [Int]) 2. How to get access to Nominator.name using reflection? When extracting values we have json and type of target instance, in this example classOf[Lotto]. It is not clear to me how those traits should be reflected at runtime. Cheers Joni On Sep 14, 1:31 am, marius d. marius.dan...@gmail.com wrote: On Sep 13, 3:15 pm, Joni Freeman freeman.j...@gmail.com wrote: Hi, That annotation is used to configure the json path when extracting values. By default the extraction code assumes that case class parameter names match with json field names. For instance these match: case class Foo(bar: String, baz: Int) { bar: qwerty, baz: 10 } But sometimes json field names can contain characters which are not allowed in Scala identifiers. For example: { foo-bar: qwerty, baz: 10 } Now, to able to extract this we have to somehow tell the extractor the exact path explicitly. Currently @path annotation is used for that: case class Foo(@path(foo-bar) bar: String, baz: Int) I don't see how a trait can accomplish this, maybe I'm missing something? The reason why it is in Java is that Scala annotations are not accessible at runtime. Right but I'd also suggest removing Java code from Lift stack. The above can be easily achieved by introducing a trait such as: case class Foo(bar: String with Nominator, baz: Int) Lift is a 100% Scala code with zero Java code. We also have strong opinions in the team that we should stay away from annotations. one option would be something like this: Lift would have : trait Nominator{ def name : String } In user's code: case class Foo(bar: String with MyNominator, baz: Int) trait MyNominator extends Nominator { def name = foo-bar } Yes it is more verbose then the annotation but IMHO it is more Scala- ish Lift-ish. Cheers Joni On Sep 13, 11:03 pm, Timothy Perrett timo...@getintheloop.eu wrote: Just had a browse over the latest commit and found the following in path.java: @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface path { public String value(); } Any reason were not using a trait etc to complete the same functionality? Cheers, Tim --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to liftweb@googlegroups.com To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~--~~~~--~~--~--~---
[Lift] Re: Why isn't this a trait in lift-json?
Using back ticks could work, I'll have to check that out. Another approach is to use map function, it works but there's a small performance and verbosity hit. import net.liftweb.json.JsonParser.parse import net.liftweb.json.JsonAST.JField implicit val formats = net.liftweb.json.DefaultFormats case class Winner(id: Long, numbers: List[Int]) case class Lotto(id: Long, winningNumbers: List[Int], winners: List [Winner], drawDate: Option[java.util.Date]) val json = parse( {lotto: { id: 5, winning-numbers: [2,45,34,23,7,5,3], draw-date: 2009-09-14T18:00:00Z, winners: [ {winner-id: 23, numbers: [2,45,34,23,3,5] }, {winner-id: 54, numbers:[52,3,12,11,18,22] } ] } } ) val json2 = json map { case JField(winning-numbers, x) = JField(winningNumbers, x) case JField(draw-date, x) = JField(drawDate, x) case JField(winning-id, x) = JField(id, x) case x = x } json2.extract[Lotto] So, I can remove @path feature (and maybe reintroduce it when Scala gets runtime visible annotations) if the community feels that Java annotations should not be used. Cheers Joni On Sep 14, 8:14 am, Naftoli Gugenheim naftoli...@gmail.com wrote: Can't you require back ticks and name the case class members the same as in the JSON? Also if it comes to traits you may as well just allow an adapter that can read and write values -- maybe a map of String to setter/getter functions. - Joni Freemanfreeman.j...@gmail.com wrote: Hi, Here's another example. {lotto: { id: 5, winning-numbers: [2,45,34,23,7,5,3], draw-date: 2009-09-14T18:00:00Z, winners: [ {winner-id: 23, numbers: [2,45,34,23,3,5] }, {winner-id: 54, numbers:[52,3,12,11,18,22] } ] } } At the moment I'm extracting this with following case class structure. case class Winner(@path(winner-id) id: Long, numbers: List[Int]) case class Lotto(id: Long, @path(winning-numbers) winningNumbers: List[Int], winners: List[Winner], �...@path(draw-date) drawDate: Option[Date]) Using a trait approach it would be something like: case class Winner(id: Long with WinnerIdNominator, numbers: List[Int]) case class Lotto(id: Long, winningNumbers: List[Int] with WinningNumbersNominator, winners: List[Winner], drawDate: Option[Date] with DrawDateNominator) trait WinnerIdNominator extends Nominator { def name = winner-id } trait WinningNumbersNominator extends Nominator { def name = winning-numbers } trait DrawDateNominator extends Nominator { def name = draw-date } Now, there's some problems. 1. Mixin a trait with a primitive fails: scala case class Winner(id: Long with WinnerIdNominator, numbers: List [Int]) console:5: error: ambiguous reference to overloaded definition, both method == in class Object of type (AnyRef)Boolean and method == in class Long of type (Long)Boolean match argument types (Long with WinnerIdNominator) case class Winner(id: Long with WinnerIdNominator, numbers: List [Int]) 2. How to get access to Nominator.name using reflection? When extracting values we have json and type of target instance, in this example classOf[Lotto]. It is not clear to me how those traits should be reflected at runtime. Cheers Joni On Sep 14, 1:31?am, marius d. marius.dan...@gmail.com wrote: On Sep 13, 3:15?pm, Joni Freeman freeman.j...@gmail.com wrote: Hi, That annotation is used to configure the json path when extracting values. By default the extraction code assumes that case class parameter names match with json field names. For instance these match: case class Foo(bar: String, baz: Int) { bar: qwerty, baz: 10 } But sometimes json field names can contain characters which are not allowed in Scala identifiers. For example: { foo-bar: qwerty, baz: 10 } Now, to able to extract this we have to somehow tell the extractor the exact path explicitly. Currently @path annotation is used for that: case class Foo(@path(foo-bar) bar: String, baz: Int) I don't see how a trait can accomplish this, maybe I'm missing something? The reason why it is in Java is that Scala annotations are not accessible at ?runtime. Right but I'd also suggest removing Java code from Lift stack. The above can be easily achieved by introducing a trait such as: case class Foo(bar: String with Nominator, baz: Int) Lift is a 100% Scala code with zero Java code. We also have strong opinions in the team that we should stay away from annotations. one option would be something like this: Lift would have : trait Nominator{ ? def name : String } In user's code: case class Foo(bar: String with MyNominator, baz: Int) trait MyNominator extends Nominator { ?def name = foo-bar } Yes it is more verbose then the annotation but IMHO it is more Scala- ish Lift-ish. Cheers Joni On Sep 13, 11:03?pm
[Lift] Re: XML - JSON converter?
Ok, added. This is a quick hack just to explore the problem so expect bugs, holes in logic and such. Example usage: http://github.com/dpp/liftweb/blob/f974b41c56afa500e9d93371f0ce21bde3c854ce/lift-json/src/test/scala/net/liftweb/json/XmlExamples.scala Cheers Joni On Sep 3, 2:40 am, David Pollak feeder.of.the.be...@gmail.com wrote: Cool... I'd be interested in you pushing this to master and letting people use it and give feedback. On Wed, Sep 2, 2009 at 2:40 PM, Joni Freeman freeman.j...@gmail.com wrote: Hi, I just quickly spiked this and following works on my local branch: scala val xml = foos foo id1/id nameHarry/name /foo foo id2/id nameDavid/name /foo /foos scala val json = toJson(xml) scala compact(render(json)) {foos:{foo:[{id:1,name:Harry},{id:2,name:David}]}} scala val json2 = json map { case JField(id, JString(s)) = JField(id, JInt(s.toInt)) case x = x } scala compact(render(json2)) {foos:{foo:[{id:1,name:Harry},{id:2,name:David}]}} This could be quite useful addition. However, I have at least one concern. What kind of processing instructions will eventually be needed for this to be generic enough? For instance, lets change the example XML to: foos foo id1/id nameHarry/name /foo /foos This would still be valid when validating against original XML's DTD, but the generated JSON structure would be something quite different (no arrays): {foos:{foo:{id:1,name:Harry}}} Cheers Joni -- Lift, the simply functional web frameworkhttp://liftweb.net Beginning Scalahttp://www.apress.com/book/view/1430219890 Follow me:http://twitter.com/dpp Git some:http://github.com/dpp --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to liftweb@googlegroups.com To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~--~~~~--~~--~--~---
[Lift] Re: XML - JSON converter?
Hi, I just quickly spiked this and following works on my local branch: scala val xml = foos foo id1/id nameHarry/name /foo foo id2/id nameDavid/name /foo /foos scala val json = toJson(xml) scala compact(render(json)) {foos:{foo:[{id:1,name:Harry},{id:2,name:David}]}} scala val json2 = json map { case JField(id, JString(s)) = JField(id, JInt(s.toInt)) case x = x } scala compact(render(json2)) {foos:{foo:[{id:1,name:Harry},{id:2,name:David}]}} This could be quite useful addition. However, I have at least one concern. What kind of processing instructions will eventually be needed for this to be generic enough? For instance, lets change the example XML to: foos foo id1/id nameHarry/name /foo /foos This would still be valid when validating against original XML's DTD, but the generated JSON structure would be something quite different (no arrays): {foos:{foo:{id:1,name:Harry}}} Cheers Joni --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to liftweb@googlegroups.com To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~--~~~~--~~--~--~---